排列算法
从集合S(n)中,任取k(k≤n)个元素,按照一定的顺序(有序性)排成一列,叫做集合S的一个k-排列。
从集合S(n)中,取出的k-排列的总个数,叫做集合S的k-排列数。
排列符号:
这里介绍3种排列形式:
1.全排列。
2.不重复全排列。
3.选择排列。
1.全排列
从集合S(n)中,取出的所有的n-排列。规模数为nPn = n!。
1)交换_递归
代码中调用的函数Swap,功能为:交换两个元素
//交换 递归
//p:表示递归到第p层
typedef char ElemType;
void _full_prem_swap_recursion(ElemType *A, int N, int p)
{
static int count = 1;
if (p == N)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < N; ++i)
{
cout<<A[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = p; i < N; ++i)
{
Swap(A[i], A[p]);//交换
_full_prem_swap_recursion(A, N, p + 1);
Swap(A[i], A[p]);//恢复
}
}
void full_prem_swap_recursion(ElemType *A, int N)
{
_full_prem_swap_recursion(A, N, 0);
}
输入:A B C
输出:
2)选择_递归
typedef char ElemType;
typedef struct stElemNode
{
ElemType value;
unsigned char num;
} ElemTypeEx;
template< class T > void SafeDelete( T*& pVal )
{
delete pVal;
pVal = NULL;
}
template< class T > void SafeDeleteArray( T*& pVal )
{
delete[] pVal;
pVal = NULL;
}
//全排列
//选择递归
void _full_prem_select_recursion(ElemTypeEx *A, int N, ElemType *choosed, int p)
{
static int count = 1;
if (p == N)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < N; ++i)
{
cout<<choosed[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = 0; i < N; ++i)
{
if (A[i].num > 0)
{
--A[i].num; //可用次数减1
choosed[p] = A[i].value;
_full_prem_select_recursion(A, N, choosed, p+1);
++A[i].num; //可用次数恢复
}
}
}
void full_prem_select_recursion(const ElemType *A, int N)
{
ElemTypeEx *A_Ex = new ElemTypeEx[N];
for (int i = 0; i < N; ++i)
{
A_Ex[i].value = A[i];
A_Ex[i].num = 1;
}
ElemType *choosed = new ElemType[N];
_full_prem_select_recursion(A_Ex, N, choosed, 0);
SafeDeleteArray(A_Ex);
SafeDeleteArray(choosed);
return;
}
输入:A B C
输出:
2.不重复全排列
集合S(m)中有相异元素n(1 <= n <= m)个,生成的排列中会有重复的,需要剔除。规模数为:
1)交换_递归
//不重复全排列
//交换 递归
//p:表示递归到第p层
typedef char ElemType;
void _unrepeat_prem_swap_recursion(ElemType *A, int N, int p)
{
static int count = 1;
if (p == N)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < N; ++i)
{
cout<<A[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = p; i < N; ++i)
{
//减枝
//如果A[i]与A[p...i-1]的任一元素相同,则表示这个待生成的序列是重复的,需要跳过
bool find = false;
for (int j = p; j < i; ++j)
{
if (A[i] == A[j])
{
find = true;
break;
}
}
if (find)
{
continue;
}
Swap(A[i], A[p]);//交换
_unrepeat_prem_swap_recursion(A, N, p + 1);
Swap(A[i], A[p]);//恢复
}
}
void unrepeat_prem_swap_recursion(ElemType *A, int N)
{
_unrepeat_prem_swap_recursion(A, N, 0);
}
输入:A A C D
输出:
2)选择_递归
//不重复全排列
//选择 递归
//p:表示递归到第p层
void _unrepeat_prem_select_recursion(ElemTypeEx *A, int N, int M, ElemType *choosed, int p)
{
static int count = 1;
if (p == M)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < M; ++i)
{
cout<<choosed[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = 0; i < N; ++i)
{
if (A[i].num > 0)
{
--A[i].num; //可用次数减1
choosed[p] = A[i].value;
_unrepeat_prem_select_recursion(A, N, M, choosed, p+1);
++A[i].num; //可用次数恢复
}
}
}
//不重复全排列
void unrepeat_prem_select_recursion(const ElemType *A, int N)
{
ElemTypeEx *A_Ex = new ElemTypeEx[Count_unrepeat(A,N)];
int M = 0;
Compress(A, N, A_Ex, M);
ElemType *choosed = new ElemType[N];
_unrepeat_prem_select_recursion(A_Ex, M, N, choosed, 0);
SafeDeleteArray(A_Ex);
SafeDeleteArray(choosed);
}
输入:A A C D
输出:
3.选择排列
从集合S(n)中,取出的所有的k-排列。规模数为nPk。
1)交换_递归
//选择排列 P(N, M)
//交换递归
//p:表示递归到第p层
typedef char ElemType;
void _select_prem_swap_recursion(ElemType *A, int N, int M, int p)
{
static int count = 1;
if (p == M)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < M; ++i)
{
cout<<A[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = p; i < N; ++i)
{
Swap(A[i], A[p]);//交换
_select_prem_swap_recursion(A, N, M, p + 1);
Swap(A[i], A[p]);//恢复
}
}
void select_prem_swap_recursion(ElemType *A, int N, int M)
{
_select_prem_swap_recursion(A, N, M, 0);
}
输入:A B C k = 2
输出:
2)选择_递归
//选择排列
//选择递归
//p:表示递归到第p层
typedef char ElemType;
typedef struct stElemNode
{
ElemType value;
unsigned char num;
} ElemTypeEx;
void _select_prem_select_recursion(ElemTypeEx *A, int N, int M, ElemType *choosed, int p)
{
static int count = 1;
if (p == M)
{
cout<<"["<<count<<"\t] = ";
for (int i = 0; i < M; ++i)
{
cout<<choosed[i]<<" ";
}
cout<<endl;
count++;
return;
}
for (int i = 0; i < N; ++i)
{
if (A[i].num > 0)
{
--A[i].num; //可用次数减1
choosed[p] = A[i].value;
_select_prem_select_recursion(A, N, M, choosed, p+1);
++A[i].num; //可用次数恢复
}
}
}
void select_prem_select_recursion(const ElemType *A, int N, int M)
{
ElemTypeEx *A_Ex = new ElemTypeEx[N];
for (int i = 0; i < N; ++i)
{
A_Ex[i].value = A[i];
A_Ex[i].num = 1;
}
ElemType *choosed = new ElemType[N];
_select_prem_select_recursion(A_Ex, N, M, choosed, 0);
SafeDeleteArray(A_Ex);
SafeDeleteArray(choosed);
return;
}
输入:A B C k = 2
输出:
常见的排列有以上三种,若有其他形式的排列,可以通过上面的三种组合出来。
如想了解常见的组合算法的实现,可以参考组合算法实现。