C++输出全排列递归算法详细解释

参考博文链接:https://blog.csdn.net/a358463121/article/details/45543879

运用了图的遍历算法:DFS深度优先遍历

中心思想: 
设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}. 
Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。 
(1)当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素; 
(2)当n>1时,Perm(R)可由(r1)+Perm(R1),(r2)+Perm(R2),…,(rn)+Perm(Rn)构成。

那么具体程序要怎么实现呢?我们来个实际的例子,假设有一数列1,2,3,4 
那么1,2,3,4的全排列 
perm({1,2,3,4})=1perm({2,3,4})+2perm({1,3,4})+3perm({1,2,4})+4perm(1,2,3) 
那么我们只要将每个数,与第一个数交换不就可以得到下一个序列了吗? 
比如{1,2,3,4}第一个与第二个数交换,那么不就得到2 {1,3,4}了,接下来我们用一个实际的例子说明该程序是怎样运行的

具体算法流程:
数列:{1,2,3} 第一个与第一个交换 
可以得到1 {2,3} 将序列{2,3}放进perm函数递归,然后

——递归{2,3} 
数列{2,3}第一个与第一个交换 
得到2{3} ,输出1,2,3 (此时low=high,因为序列{3}只有一位数,因此输出列表list) 
数列{2,3}第一个与第一个交换回来,结果仍然是{2,3} 
数列{2,3}第一个与第二个交换 
得到3{2},输出1,3,2 
{3,2}又第一个与第二个交换回来,变回{2,3} 
—–{2,3}递归完毕序列恢复原状{1,2,3}

数列:{1,2,3} 第一个与第二个交换 
可以得到2,{1,3} 
——递归{1,3} 
数列{1,3}第一个与第一个交换 
得到1{3} ,输出2,1,3 
数列{1,3}第一个与第一个交换回来,结果仍然是{1,3} 
数列{1,3}第一个与第二个交换 
得到3{1},输出2,3,1 
{3,1}又第一个与第二个交换回来,变回{1,3} 
—–{1,3}递归完毕 
序列{2,1,3}第一个与第二个交换 
序列恢复原状{1,2,3}

数列:{1,2,3} 第一个与第三个交换 
可以得到3,{1,2} 
——递归{1,2} 
数列{1,2}第一个与第一个交换 
得到1{2} ,输出3,1,2 
数列{1,2}第一个与第一个交换回来,结果仍然是{1,2} 
数列{1,2}第一个与第二个交换 
得到2{1},输出3,2,1 
{2,1}又第一个与第二个交换回来,变回{1,2} 
—–{1,2}递归完毕 
序列{3,1,2}第一个与第二个交换 
序列恢复原状{1,2,3}

算法可以简单地写作 
perm({1,2,3})=1perm({2,3})+2perm({1,3})+3perm({1,2}) 
perm({2,3})=2perm({3})+3perm({2}) 
perm({1,3})=1perm({3})+3perm({1}) 
perm({1,2})=1perm({2})+2perm({1})

c++代码:

#include <iostream>
using namespace std;
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
}
void perm(int list[],int low,int high){
    if(low==high){   //当low==high时,此时list就是其中一个排列,输出list
        for(int i=0;i<=low;i++)
            cout<<list[i];
        cout<<endl;
    }else{
        for(int i=low;i<=high;i++){//每个元素与第一个元素交换
            swap(list[i],list[low]); 
            perm(list,low+1,high); //交换后,得到子序列,用函数perm得到子序列的全排列
            swap(list[i],list[low]);//最后,将元素交换回来,复原,然后交换另一个元素
        }
    }
}
int main()
{

int list[]={1,2,3};
perm(list,0,2);
return 0;
}

程序结果:

123
132
213
231
321
312

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值