您的位置:首页 > 编程语言 > C语言/C++

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

2016-04-18 01:46 405 查看
原文地址:http://www.2cto.com/kf/201505/397602.html

中心思想:

设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})

#include <iostream>
using namespace std;
int n = 0;

void swap(char *a ,char *b)
{
int m ;
m = *a;
*a = *b;
*b = m;
}

void perm(char list[],int k, int m )
{
int i;
if(k >m)
{
for(i = 0 ; i <= m ; i++)
{
cout<<" "<<list[i];

}
cout<<endl;
n++;
}
else
{
for(i = k ; i <=m;i++)
{
swap(&list[k],&list[i]);
perm(list,k+1,m);
swap(&list[k],&list[i]);
}
}
}

int main()
{
char list[] ="1234";
perm(list,0,3);
cout<<"total:"<<n<<endl;
return 0;
}


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