全排列的实现

来源:互联网 发布:mac磁盘名称 编辑:程序博客网 时间:2024/05/18 09:09

实现方法

文章主要讲两种实现全排列的方法:
1. 使用C++的STL模板实现数字或字符的全排列。
2. 使用递归的思想实现数字或字符的全排列。

STL模板实现

在C++的模板中,有一对专门用于实现数字或字符全排列的模板:next_permutation(_BIter, _BIter)和prev_permutation(_BIter, _BIter)。前者实现向后排列,后者实现向前排列,即前者在原顺序上依次产生较大的排列,后者则相反。
举个例子:假设需要产生以“354”为基础的全排列,使用next_permutation(_BIter, _BIter),则下一个排列为“435”,而使用prev_permutation(_BIter, _BIter),则下一个排列为“345”。

#include <bits/stdc++.h>using namespace std;int main(){    string ss("1234");    while(next_permutation(ss.begin(), ss.end()))         cout << ss << endl;    return 0;   }

输出结果为:

12431324134214231432213421432314234124132431312431423214324134123421412341324213423143124321

从上面的结果中我们可以发现没有原始排列“1234”,这时因为该模板实现的是以原始排列为基础依次产生后序排列,所以并不会产生原始的排列,这里需要注意下!


如果我们把上述代码中的next_permutation(ss.begin(), ss.end())换成prev_permutation(ss.begin(), ss.end())会产生什么结果呢?
结果如下:

什么都没有,这又是为什么呢?这是因为prev_permutation(_BIter, _BIter)产生的是以“1234”为基础的更小的排列,但是“1234”已经是最小的排列了,那么自然就不会产生任何结果了。既然是这样那我们把原ss改为“4321”是不是就可以了呢,我们看一下运行结果:

43124231421341324123342134123241321431423124243124132341231421432134143214231342132412431234

果然实现了全排列。(还是要注意,结果中同样没有原排列“4321”


从上面的例子中不难看出,如果给你一个无序的字符串或者数组,那么你首先需要对它进行排序,然后才能使用模板来求全排列。
比如:

#include <bits/stdc++.h>using namespace std;int main(){    int num[5] = {3,2,4,1,5};    sort(num, num + 5);//先排序    while(next_permutation(num, num + 5))    {        for(int i = 0; i < 5; ++i)            cout << num[i];        cout << endl;    }    return 0;}

递归实现

设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。
1.当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素。
2.当n>1时,Perm(R)可由(r1)+Perm(R1),(r2)+Perm(R2),…,(rn)+Perm(Rn)构成。

举例“123”:
1+Perm(2,3)→1+(2+Prem(3)) = 123
1+Perm(2,3)→1+(3+Perm(2)) = 132
2+Perm(1,3)→2+(1+Perm(3)) = 213
2+Perm(1,3)→2+(3+Perm(1)) = 231
3+Perm(2,1)→3+(2+Perm(1)) = 321
3+Perm(2,1)→3+(1+Perm(2)) = 312

实现代码如下:

#include <bits/stdc++.h>using namespace std;void permutation(int arry[], int low, int high){    if(low == high)    {        //当low==high时,此时arry就是其中一个排列,输出arry        for(int i = 0; i <= low; ++i)            cout << arry[i];        cout << endl;    }    else    {        for(int i = low; i <= high; ++i) //每个元素与第一个元素交换        {            swap(arry[i], arry[low]);            permutation(arry, low + 1, high); //递归调用            swap(arry[i], arry[low]);//最后,将元素交换回来,复原        }    }}int main(){      int num[4] = {1,2,3,4};    permutation(num, 0, 3);    return 0;}

运行结果:

123412431324134214321423213421432314234124312413321432413124314234123421423142134321431241324123

递归方法实现参考于:算法设计-全排列递归

1 0