全排列问题:
求n个元素的全排列,n个元素中允许出现重复元素,通过实例验证算法。
思路:
设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。集合X中元素的全排列记为Perm(X)。(ri)Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。R的全排列可归纳定义如下:
当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;
当n>1时,Perm(R)由(r1)Perm(R1),(r2)Perm(R2),…,(rn)Perm(Rn)构成。
算法Perm(list,k,m)递归地产生所有前缀是list[0:k-1],且后缀是list[k:m]的全排列的所有排列。函数调用Perm(list,0,n-1)则产生list[0:n-1]的全排列。
在一般情况下,k<m。算法将list[k:m]中的每一个元素分别与list[k ]中的元素交换。然后递归地计算list[k+1:m]的全排列,并将计算结果作为list[0:k]的后缀算法中IsSwap()是用于交换两个变量值的内联函数。
算法实现:
#include<iostream>
using namespace std;
template<class Type>
bool IsSwap(Type list[], Type nBegin, Type nEnd) {
for (int i = nBegin; i < nEnd; i++)
if (list[i] == list[nEnd])
return false;
return true;
}
template<class Type>
void perm(Type 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++) {
if (IsSwap(list,k,i)){
swap(list[k], list[i]);
perm(list, k + 1, m);
swap(list[k], list[i]);
}
}
}
}
template<class Type>
bool swap(Type &a, Type &b) {
Type temp = a;
a = b;
b = a;
return true;
}
int main() {
int arr[] = { 1,1,2 };
perm(arr,0,2);
system("pause");
}