一、问题
设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列。
二、思路
其实就是将整个序列A={,,......}的每个元素一一提到序列A首个位置即A[i] ()处,然后对A[i+1]......A[j]这些元素组成的序列全排列,也就是对除了首元素的剩余序列递归进行全排列,直到剩余序列只剩一个元素,打印当前序列。注意每次将元素调到当前序列首个位置、然后对剩余序列全排列之后,要将元素换回原来的位置。全排列的结果总共有n!种,比如当对于序列{1,2,3},n=3,那么结果就有3!=6种。
三、代码
#include <iostream>
using namespace std;
void swap (int &a, int &b)
{
int temp=a;
a=b;
b=temp;
}
// list[k:m]的所有排列,k是序列首下标,m是序列最后一个下标
void perm (int list[], int k, int 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]);
}
}
int main()
{
int A[]= {1,2,3};
perm(A,0,2);
system("pause");
return 0;
}
运行结果:
。。但是上面的算法只能找出元素都不相同的序列的全排列,像我们遇到{"1","2","2","3"}这样有重复元素的序列就尴尬了,所以改进下,同时我还把数据类型改了,反正都一样的:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void swap (string &a, string &b)
{
string temp=a;
a=b;
b=temp;
}
// list[k:m]的所有排列,k是序列首下标,m是序列最后一个下标
void perm (vector<string> list, int k, int m)
{
if (k==m)
{
string s="";
for (int i=0; i<=m; i++)
{
s.append(list[i]);
}
cout<<s<<endl;
}
else
for (int i=k; i<=m; i++)
{
bool flag=false;
//检查重复元素
for(int p=k; !flag && p<i; p++)
{
if(list[p]==list[i])
{
flag=true;
}
}
if(flag)continue;
swap(list[k], list[i]);
perm(list, k+1, m);
swap(list[k], list[i]);
}
}
int main()
{
string A0[]= {"1","2","2","3"};
vector<string> A(A0,A0+4);
perm(A,0,3);
system("pause");
return 0;
}
运行结果:
可以看到结果没有重复的、啦!