一、问题描述
假如有一个序列R={1,2,3},那么它的全排列为:123,132,213,231,312,321,共六种。现有序列R={1,2,3,4,...,n},求它的全排列。
二、分析
此问题可以通过递归解决,设R={r1,r2,....,rn}是要进行排列的n个元素,Ri=R-{ri}。集合R的全排列记为Perm(R)。R的全排列可归纳定义如下:
1.当n=1时,Perm(R)=r,其中r是集合R中的唯一元素。
2.当n>1时,Perm(R)由r1Perm(R1),r2Perm(R2),...,rnPerm(Rn)构成。
以R={1,2,3}为例,n=3>1,则Perm({1,2,3})由{1}Perm({2,3}),{2}Perm({1,3}),{3}Perm({1,2})构成。
仅分析{1}Perm({2,3}),Perm({2,3})由{2}Perm({3}),{3}Perm({2})构成。
仅分析{2}Perm({3}),由于n=1只有一个元素,理所当然的,Perm({3})=3;
所以第一个排列就是:1,2,3。剩下的排列以此类推。
三、算法实现(c#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace permutation
{
class Program
{
static void swap(ref int i,ref int j)//交换两个变量的值
{
int temp;
temp = i;
i = j;
j = temp;
}
static void perm(int[] a,int k ,int m)//排列算法
{
if (k == m)//到达最后一个元素
{
foreach (int v in a)
Console.Write(v);
Console.WriteLine();
}
else
{
for (int i = k; i <= m; i++)
{
swap(ref a[k], ref a[i]);
perm( a, k + 1, m);
swap(ref a[k], ref a[i]);
}
}
}
static void Main(string[] args)
{
int[] a = new int[4];
for (int i = 0; i < 4; i++)
{
a[i] = i+1;
}
perm(a,0,3);
}
}
}
说明:
算法Perm(a,k,m)递归的产生所有前缀是a[0:k-1],且后缀是a[k:m]的全排列的所有排列。例如Perm(a,0,n-1)则产生a[0:n-1]的全排列。一般情况下,k<m。算法将a[k:m]中的每一个元素分别与a[k]的元素交换。然后递归的计算a[k+1:m]的全排列,并将计算结果作为a[0:k]的后缀。