全排列的实现

实现方法

文章主要讲两种实现全排列的方法:
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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值