您的位置:首页 > 其它

全排列

2017-04-19 16:22 288 查看
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。

如1,2,3三个元素的全排列为:

1,2,3

1,3,2

2,1,3

2,3,1

3,1,2

3,2,1

共3*2*1=6种 3!

公式:

全排列数f(n)=n!(定义0!=1)

递归实现:

#include <iostream>
using namespace std;

static int count = 0;
void Perm(int* array, int size, int N)
//N是考虑数组中需要变化的后几位数,即就是前(size-N)位不变,对后N位进行排列
//N为5表示数组不需要变化,直接打印即可,只有一种排列方法
//N为0表示五位数均要排列
{

if(size == N)
{
for(int i=0; i<size; ++i)
{
cout<<array[i]<<" ";
}
cout<<endl;
count++;
cout<<"count = "<<count<<endl;
}
else
{
for(int i=N; i<size; ++i)
{
swap(array[i], array
);
Perm(array, size, N+1);
swap(array[i], array
);

}
}
}

void FunTest()
{
int array[] = {1, 2, 3};
Perm(array, sizeof(array)/sizeof(array[0]), 0);
}
int main()
{
FunTest();
system("pause");
return 0;
}


运行结果如下:



这样的方法存在问题:如果存在相同的数据,回打印多次,显然这并不是我们所期望的全排列。



可以看出第一种和第五种重复,第三种和第四种重复,第二种和第六种重复,所以实际上的全排列只有三种,但明显输出了六种,所以应该规避这种错误,所以出现了如下的代码:

//去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。

#include <iostream>
using namespace std;

static int count = 0;

bool IsSwap(int *array, int start, int end)
{
for (int i = start; i < end; i++)
if (array[i] == array[end])
return false;
return true;
}

void Perm(int* array, int size, int N)
//N是考虑数组中需要变化的后几位数,即就是前(size-N)位不变,对后N位进行排列
//N为5表示数组不需要变化,直接打印即可,只有一种排列方法
//N为0表示五位数均要排列
{
if(size == N)
{
for(int i=0; i<size; ++i)
{
cout<<array[i]<<" ";
}
cout<<endl;
count++;
cout<<"count = "<<count<<endl;
}
else
{
for(int i=N; i<size; ++i)
{
if(IsSwap(array, N, i))
//判断如果出现重复的就不进行排序
{
swap(array[i], array
);
Perm(array, size, N+1);
swap(array[i], array
);
}
}
}
}

void FunTest()
{
int array[] = {1, 2, 1};
Perm(array, sizeof(array)/sizeof(array[0]), 0);
}

int main()
{
FunTest();
system("pause");
return 0;
}


运行结果:

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