实现方法
文章主要讲两种实现全排列的方法:
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;
}
输出结果为:
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
从上面的结果中我们可以发现没有原始排列“1234”,这时因为该模板实现的是以原始排列为基础依次产生后序排列,所以并不会产生原始的排列,这里需要注意下!
如果我们把上述代码中的next_permutation(ss.begin(), ss.end())
换成prev_permutation(ss.begin(), ss.end())
会产生什么结果呢?
结果如下:
什么都没有,这又是为什么呢?这是因为prev_permutation(_BIter, _BIter)产生的是以“1234”为基础的更小的排列,但是“1234”已经是最小的排列了,那么自然就不会产生任何结果了。既然是这样那我们把原ss改为“4321”是不是就可以了呢,我们看一下运行结果:
4312
4231
4213
4132
4123
3421
3412
3241
3214
3142
3124
2431
2413
2341
2314
2143
2134
1432
1423
1342
1324
1243
1234
果然实现了全排列。(还是要注意,结果中同样没有原排列“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;
}
运行结果:
1234
1243
1324
1342
1432
1423
2134
2143
2314
2341
2431
2413
3214
3241
3124
3142
3412
3421
4231
4213
4321
4312
4132
4123
递归方法实现参考于:算法设计-全排列递归