您的位置:首页 > 其它

递归实现全排列问题

2017-09-23 13:20 211 查看
最近在上算法课,学到递归和分治策略总觉得有些难以理解……怎么说呢我总觉得递归的代码很简单,但是真正在看代码想象递归过程的时候想着想着就想不通了,准确来说自己确实不知道递归到哪个环节了并且这一层递归结束后到底该返回到哪里去……哇真的感觉要笨死==算法作业做到第二题就被卡住了,不知道该怎么写……舍友告诉我说这是一个全排列问题,我看了看代码想象着这个递归过程却一次又一次的懵逼:(老师知道也许会被气死毕竟上课讲过……百度了一下也和书上的代码差不多……后来看了一遍又一遍代码,我突然意识到,这是全排列???我一直将全排列和快速排序弄混了,所以我纠结了许久的为什么全排列里面没有比较大小再交换顺序的代码在这段程序里面是不可能存在的,尴尬……自己给自己挖了坑跳进去还出不来了……好了言归正传,还是来说一下递归解决全排列的问题吧。

设R={r1,r2,…,rn}是要进行全排列的n个元素,Ri=R-{ri}集合X中元素的全排列记为Perm(X)。R的全排列可归纳定义如下:

1.当n=1时,Perm(R)={r},其中r是集合R中唯一的元素。

2.当n>1时,Perm(R)由(r1)Perm(R1)、(r2)Perm(R2)、……、(rn)Perm(Rn)构成.

根据分治法的设计思想,将一个难以解决的大问题分割成一些小规模的相同问题,以便于各个击破分而治之。说的直白点,就是通过递归的方式把集合的规模逐步缩小。比如集合R={a,b,c,d},先固定a,递归求{b,c,d}的全排列,再固定b,递归求{c,d}的全排列,……以此类推,直到剩下最后一个字母,输出这段排列。为了方便理解这个问题,我画了一个图。



箭头后面就是每轮递归结束时输出的结果,下划线标注的则是每次固定的字母。固定b、c、d和上面的过程差不多我就省略了没写,不小心把集合的大括号写成了小括号懒得再写一次了就这样将就着看吧:)

该放代码了,我就上面的图写了一段程序。

#include <iostream>
using namespace std;

void perm(char list[],int k,int m)
{
//产生list[k:m]的全排列
if(k==m)
{
//只剩下一个元素
for(int i=0;i<=m;i++)
cout<<list[i];
cout<<endl;
}
else   //还有多个元素带排列,递归产生排列
{
for(int i=k;i<=m;i++)
{
swap(list[k],list[i]);
perm(list,k+1,m);
swap(list[k],list[i]);
}
}
}

void swap(char a,char b)   //交换
{
char temp=a;
a=b;
b=temp;

}

int main()
{
char list[4];
cin>>list;
cout<<endl;
perm(list,0,3);
return 0;
}
输入abcd,运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: