C++ 标准库 permutation

首先,permutation指的是对元素的重排,比如a , b , c 三个元素的所有的重排为    abc, acb, bac,bca,cab,cba 总共 3!  = 6 中情况,但是如何声称这六种情况呢,C++标准库定义了函数 next_permutation,来生成一组元素的所有的全排列。

首先,了解该函数的声明以及实现:

函数声明为: [摘自 www.cplusplus.com]

std::next_permutation

default (1)
template <class BidirectionalIterator>
  bool next_permutation (BidirectionalIterator first,
                         BidirectionalIterator last);
custom (2)
template <class BidirectionalIterator, class Compare>
  bool next_permutation (BidirectionalIterator first,
                         BidirectionalIterator last, Compare comp);

此两者在C++的标准库中被实现为模板的形式。

参数说明:

first last  
其中的迭代器  first 和 last 用来表示元素的范围 [ first, last ) 不对称边界。

再来就是该迭代器的类型为双向迭代器,那么也就是说 随机迭代器和双向迭代器可以作为该函数的参数传入。

Compare comp   是用来比较的函数,也就是说用来决定生成的重排的顺序函数,默认使用的是opeartor<符号,当然你自己也可以定义自己的比较函数,作为函数指针传入,或者是定义仿函数,传入函数对象,

返回值:

如果在该comp函数下,下一个重拍序列存在,则返回true,走则返回false,也就是说这一次的重拍序列已经是最后一个重排序列了。

比如,如果采用的是operator<作为比较函数的话,那么 {1,2,3}的最后一个重排就是321,第一个重排就是123,在321之后再调用next_premutation,返回false,但是该函数会将原来的数组排列为 1,2,3。

副作用:

该函数会修改传入的元素顺序。

执行结果为:

可以看出,该函数会自动在当前的元素的顺序基础上,生成后续的排列。也就是说,如果要生成所有的permutation的话,那么需要先将元素排序。

OK!!用法已经详解了,接下来便是要将该函数的真面目示人了。

template <class _BidirectionalIter>
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) {
  __STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator);
  __STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
                 _LessThanComparable);
  if (__first == __last) //如果传入参数为空的话,
    return false;
  _BidirectionalIter __i = __first;
  ++__i;
  if (__i == __last) //如果只有一个元素
    return false;
  __i = __last;
  --__i;

  for(;;) {
    _BidirectionalIter __ii = __i;
    --__i;
    if (*__i < *__ii) {
      _BidirectionalIter __j = __last;
      while (!(*__i < *--__j))
        {}
      iter_swap(__i, __j);
      reverse(__ii, __last);
      return true;
    }
    if (__i == __first) {
      reverse(__first, __last);
      return false;
    }
  }
}

以上为STL中的版本,该函数实现原理如下:

在当前的序列中,从尾端出发往前找到一对相邻的元素  a[ i ] 与 a[ j ] ,使得 a[ i ]  < a[ j ], (此处默认采用less函数对象),然后再从尾端出发找到一个字符
 a[ k ] ,使得 a[ i ]  < a[ k ], 此时交换 a[ k ] 与 a[ i ], 并且将a[ j --- end) 之间的所有元素逆序即可。代码实现为:

template<class bidirectional_iterator>
bool permutation(bidirectional_iterator first, bidirectional_iterator last)
{
    if(first == last) return false; //如果没有元素

    if(first + 1 == last) return false; //如果只有一个元素

    bidirectional_iterator j = last;
    --j;

    while(1)
    {
        bidirectional_iterator i = j;
        --i;
        //find a[i] < a[j] and they are adjacent
        if(*i < *j)
        {
            bidirectional_iterator k = last;
            while(!(*i < *--k)){}
            std::iter_swap(i,k); //或者是  swap(*i, *k);
            std::reverse(j,last);
            return true;
        }
        --j;
        //no such a[i] < a[i+1] pair found
        if( j == first)
        {
            //restore the first of the permutation
            std::reverse(first, last);
            return false;
        }
    }
}

上述代码中的swap函数必须是iter_swap函数,利用swap只是交换了迭代器的指针,并未实际改变元素的位。也可以使用swap(*i, *k);

关于该函数的comp对象的实际形式,接着会有一篇关于函数指针以及函数对象的博文,详细讲解。

时间: 2024-10-08 14:41:50

C++ 标准库 permutation的相关文章

3.2 标准库类型string(上)

#include <string> #include <iostream> using std::string; using std::cin; using std::cout; using std::endl; //string定义在命名空间std中 int main() { /**************3.2.1 定义和初始化string*****************/ string s1; //默认初始化,S1是一个空字符串 string S2 = s1; //S2时S

Obstack是C标准库里面对内存管理的GNU扩展

Obstack介绍 Obstack初始化 在Obstack中申请对象 释放对象 申请growing object 获取Obstack状态 数据对齐 以下是来自wiki对obstack的介绍: Obstack是C标准库里面对内存管理的GNU扩展(实际上就是GNU C library了).Obstack===Object stack.没错,Obstack就是一个栈,栈里面的元素是对象object(不是面向对象的对象哦,这里的对象单指数据元素).这些数据是动态的,也就是使用的是动态内存.这种内存管理技

C++温习-标准库-set

set,就是集合,其满足唯一性, C++中的标准库set是一个类模板, template < class T, // set::key_type/value_type class Compare = less<T>, // set::key_compare/value_compare class Alloc = allocator<T> // set::allocator_type > class set; 正常使用需要提供类别参数如 set<string>

Django的标准库django.contrib包介绍

前面我们激活了 Django 后台,我们要使用自动化的站点管理工具(django.contrib.admin),所以最好对Django.contrib进行了解,它是啥?它是一个强大的功能包,是Django的标准库. Django的标准库存放在 django.contrib 包中.每个子包都是一个独立的附加功能包. 这些子包一般是互相独立的,不过有些django.contrib子包需要依赖其他子包. 在 django.contrib 中对函数的类型并没有强制要求 .其中一些包中带有模型(因此需要你

一、Python的标准库String

一.Python的标准库String 1.查看武器 a. help(type()) name = "jane"print(help(type(name))) b. capitalize() name = "jane" print(name.capitalize()) 效果:Jane c. center() name = "jane" print(name.center(50, '-')) 效果:-----------------------jan

介绍下Python的两个标准库 os 和 sys

import sysprint(sys.path) #python 2 中报错 ....,打印的是绝对路径(***\\python\\lib\\site-packages# 第三方库,后退一级为标准库) '''import osos_sys = os.system("dir")print("---->",os_sys) #执行命令,不保存结果os.popen("dir").read #os.popen 打印的为对象地址,加上read 取出结

STL标准库-容器-list

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. list 表示非连续的内存区域,并通过一对指向首尾元素的指针双向链接起来,从而允许向前和向后两个方向进行遍历.在list 的任意位置插入和删除元素的效率都很高. 它的结构 一 定义 头文件 #include <vector> #include <iostream> #include <list> using namespace std; int main(int argc, const c

python MultiProcessing标准库使用Queue通信的注意要点

今天原本想研究下MultiProcessing标准库下的进程间通信,根据 MultiProcessing官网 给的提示,有两种方法能够来实现进程间的通信,分别是pipe和queue.因为看queue顺眼,就想着拿queue实现,后来,被坑了....于是有了这篇文章.我按照 python标准库之MultiProcessing库的研究 (1) 里面的代码来的,结果就是不断的出错,死过就是不出结果,看看程序: from multiprocessing import Pool, queues impor

python标准库Beautiful Soup与MongoDb爬喜马拉雅电台的总结

Beautiful Soup标准库是一个可以从HTML/XML文件中提取数据的Python库,它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式,Beautiful Soup将会节省数小时的工作时间.pymongo标准库是MongoDb NoSql数据库与python语言之间的桥梁,通过pymongo将数据保存到MongoDb中.结合使用这两者来爬去喜马拉雅电台的数据... Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是