【STL】全排列生成算法:next_permutation

C++/STL中定义的next_permutation和prev_permutation函数是非常灵活且高效的一种方法,它被广泛的应用于为指定序列生成不同的排列。

next_permutation函数将按字母表顺序生成给定序列的下一个较大的排列,直到整个序列为降序为止。

prev_permutation函数与之相反,是生成给定序列的上一个较小的排列。

所谓“下一个”和“上一个”,举一个简单的例子:

  对序列 {a, b, c},每一个元素都比后面的小,按照字典序列,固定a之后,a比bc都小,c比b大,它的下一个序列即为{a, c, b},而{a, c, b}的上一个序列即为{a, b, c},同理可以推出所有的六个序列为:{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a},其中{a, b, c}没有上一个元素,{c, b, a}没有下一个元素。

二者原理相同,仅遍例顺序相反,这里仅以next_permutation为例介绍算法。

(1) int 类型的next_permutation

int main()
{
    int a[3];
    a[0]=1;a[1]=2;a[2]=3;
    do
    {
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
    }while (next_permutation(a,a+3)); //参数3指的是要进行排列的长度

//如果存在a之后的排列,就返回true。如果a是最后一个排列没有后继,返回false,每执行一次,a就变成它的后继
}

输出:
 1 2 3
 1 3 2
 2 1 3
 2 3 1
 3 1 2
 3 2 1

如果改成

1 while(next_permutation(a,a+2));

则输出:
 1 2 3
 2 1 3
只对前两个元素进行字典排序

显然,如果改成

1 while(next_permutation(a,a+1));

则只输出:1 2 3
 
若排列本来就是最大的了没有后继,则next_permutation执行后,会对排列进行字典升序排序,相当于循环
 

1 int list[3]={3,2,1};
2 next_permutation(list,list+3);
3 cout<<list[0]<<" "<<list[1]<<" "<<list[2]<<endl;

输出: 1 2 3
 
(2) char 类型的next_permutation
 

int main()
{
    char ch[205];
    cin >> ch;

    sort(ch, ch + strlen(ch) );
    //该语句对输入的数组进行字典升序排序。如输入9874563102
    cout<<ch;//将输出0123456789,这样就能输出全排列了

    char *first = ch;
    char *last = ch + strlen(ch);

    do {
        cout<< ch << endl;
    }while(next_permutation(first, last));
     return 0;
}

//这样就不必事先知道ch的大小了,是把整个ch字符串全都进行排序
//若采用 while(next_permutation(ch,ch+5)); 如果只输入1562,就会产生错误,因为ch中第五个元素指向未知
//若要整个字符串进行排序,参数5指的是数组的长度,不含结束符

(3) string 类型的next_permutation
 

int main()
{
    string line;
    while(cin>>line&&line!="#")
    {
        if(next_permutation(line.begin(),line.end())) //从当前输入位置开始
        cout<<line<<endl;
        else cout<<"Nosuccesor\n";
    }
}
int main()
{
    string line;
    while(cin>>line&&line!="#")
    {
        sort(line.begin(),line.end());//全排列
        cout<<line<<endl;
        while(next_permutation(line.begin(),line.end()))
        cout<<line<<endl;
    }
}

next_permutation 自定义比较函数
 

#include<iostream> //poj 1256 Anagram
#include<cstring>
#include<algorithm>
using namespace std;
int cmp(char a,char b) //‘A‘<‘a‘<‘B‘<‘b‘<...<‘Z‘<‘z‘.
{
    if(tolower(a)!=tolower(b))
        return tolower(a)<tolower(b);
    else
        return a<b;
}
int main()
{
    char ch[20];
    int n;
    cin>>n;
    while(n--)
    {
        scanf("%s",ch);
        sort(ch,ch+strlen(ch),cmp);
        do
        {
            printf("%s\n",ch);
        }while(next_permutation(ch,ch+strlen(ch),cmp));
    }
    return 0;
}

用next_permutation和prev_permutation求排列组合很方便,但是要记得包含头文件#include <algorithm>。

虽然最后一个排列没有下一个排列,用next_permutation会返回false,但是使用了这个方法后,序列会变成字典序列的第一个,如cba变成abc。prev_permutation同理。

时间: 2024-10-09 04:07:47

【STL】全排列生成算法:next_permutation的相关文章

递归解决全排列生成算法

排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列: 全排列:当n==m时,称为全排列: 比如:集合{ 1,2,3}的全排列为: { 1 2 3} { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 2 1 } { 3 1 2 } 方法一: 我们可以将这个排列问题画成图形表示,即排列枚举树,比如下图为{1,2,3}的排列枚举树,此树和我们这里介绍的算法完全一致: 算法思路: (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀): (2)出口:如

全排列生成算法

全排列的生成算法, next_permutation_1 可以用于生成多重集的全排列,next_permutation_2不能用于多重集 #include <cstdio> #include <cstring> #include <vector> using namespace std; bool next_permutation_1(vector<int>& vec){ int n = vec.size()-1; for(;n>0;n--){

简单探讨全排列的生成算法

在研究组合数学的时候,常常能够碰见要求生成全排列的情况.下面来简单探讨全排列的递归生成算法. 现有一个序列(1,2,3),将其命名为序列S<a1,a2,a3>, 假定A(a1,a2,a3) 为这个序列的全排列,那么我们可以得到如下若干序列: <a1,A(a2,a3)>  ① <a2,A(a1,a3)>  ② <a3,A(a1,a2)>  ③ 我们再来看①,她还可以展开成如下两个序列: <a1,a2,A(a3)>  ⑤ <a1,a3,A(a2

全排列的生成算法

[复制转载] //全排列的生成算法 // 全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来.任何n个字符集的排列都可以与1-n的n个数字的排列一一对应, // 因此在此就以n个数字的排列为例说明排列的生成法. // n个字符的全体排列之间存在一个确定的线性顺序关系.所有的排列中除最后一个排列外,都有一个后继:除第一个排列外,都有一个前驱.每个排列的后继都可以从 // 它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方

C++ STL 常用算术和生成算法

C++ STL 常用算术和生成算法 accumulate() accumulate: 对指定范围内的元素求和,然后结果再加上一个由val指定的初始值. #include<numeric> vector<int> vecIntA; vecIntA.push_back(1); vecIntA.push_back(3); vecIntA.push_back(5); vecIntA.push_back(7); vecIntA.push_back(9); int iSum = accumul

c++STL之常用算术生成算法

accumulate:计算容器元素累计总和 fill:向容器中添加元素 1.accumulate #include<iostream> using namespace std; #include <vector> #include <numeric> //常用算术生成算法 void test01() { vector<int>v; for (int i = 0; i <= 100; i++) { v.push_back(i); } //参数3 起始累加

STL具体操作之next_permutation和prev_permutation函数

 next函数默认的是从小到大的顺序,pre函数默认的是从大到小的顺序: {3,1,2}用next得到的结果是{3,1,2}和{3,2,1}: 用pre得到的结果是{3,1,2},{2,3,1},{2,1,3},{1,3,2,},{1,2,3}: 原理如下: [STL]next_permutation的原理和使用 1.碰到next_permutation(permutation:序列的意思) 今天在TC上碰到一道简单题(SRM531 - Division Two - Level One),是

随机排列生成算法

这篇文章主要是一个闲文.如果您正在寻求一个理想的随机排列生成算法,直接阅读方法3,或是直接使用STL里提供的random_shuffle()方法另外请注意,这里所讨论的算法并不是新的. 什么是随机排列? 一个随机排列是一组位于随机位置的对象.给定一个对象,1, 2, 3 ... n,随机排列看起来就是,p1, p2, p3 ... pn其中px是从原来的对象集合中选取的随机值. 随机排列对于扑克牌洗牌,随机产生益智游戏,产生随机序列,或者生成一个随机子集合集(从 n 个对象中随机选出 k 个对象

[LeetCode] Permutations 排列生成算法之字典序法

字典序排序生成算法 字典序法就是按照字典排序的思想逐一产生所有排列. 例如,由1,2,3,4组成的所有排列,从小到大的依次为: 1234, 1243, 1324, 1342, 1423, 1432, 2134, 2143, 2314, 2341, 2413, 2431, 3124, 3142, 3214, 3241, 3412, 3421, 4123, 4132, 4213, 4231, 4312, 4321. 分析这种过程,看后一个排列与前一个排列之间有什么关系? 再如,设有排列(p)=276