您的位置:首页 > 其它

递归与非递归算法求序列所有排列组合

2013-11-05 23:21 309 查看
问题描述:

给定已知序列A1A2…An,求出其所有排列组合

一、递归算法

基本思路:


1. 如果n等于1,输出当前序列



2. 否则依次交换Ai(i=1,2..n-1,n)和An



3. 对于前n-1长度序列,重复1、2两步


算法复杂度O(n!),

算法缺点:如果序列中有重复字符,会出现相同排列组合。递归算法效率低。

算法优点:可以应用于所有字符串序列

二、非递归算法

基本思路:


1. 假设字符都是可比较的,每种排列组合之间都可以比较大小,A1A2…An的最小排列是P1P2…Pn(P1,p2..pn是非严格递增的)。



2. 从P1P2…Pn开始找出刚好比当前排列大的排列。



3. 循环第2步,直到得到最大的排列Pn…P2p1,算法结束。


如何找出刚好比当前排列大的,假设当前排列为B1B2…Bn,


1. 从最右开始,找到第一个递减的字符Bi,Bi<Bi+1,Bi+1>Bi+2>…>Bn,找不到就结束算法



2. 在Bn…Bi+1中找到第一个大于Bi的Bj,交换Bi和Bj,将Bi+1…Bn重新排序成递增排列,新的排列即为所求排列



3. 重复第1步


算法优点:不会出现重复排列组合

算法缺点:只能应用于可比较字符串,或需自定义比较函数

下面给出整数序列的算法代码,主要阐述思想

void Swap(int *a, int *b){
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}

void AscSort(int *array, int n){
int i, j;
for(i=n-1; i>=0; i--)
for(j=0; j<i; j++)
if(array[j]>array[j+1]) swap(&array[j], &array[j+1]);
}

void ArrayPrintf(int *array, int length){
int i;
for(i=0; i<length; i++)
printf("%d ",array[i]);
printf("\n");
}

void NonRecurLoopArray(int *array, int length){
AscSort(array, length);
ArrayPrintf(array,length);
if(length<=1) return;
while(true){
int i = length-1;
int j = length-1;
while(i>0 && array[i-1]>=array[i]) --i;
if(i <= 0) return;
while(j>i-1 && array[j]<=array[i-1]) j--;
swap(&array[i-1], &array[j]);
AscSort(&array[i], length-i);
ArrayPrintf(array,length);
}
}

void RecurLoopArray(int *array, int length, int num){
if(length==1){
ArrayPrintf(array, num);
return;
}
for(int i=0; i<length; ++i){
swap(&array[i], &array[length-1]);
RecurLoopArray(array, length-1, num);
swap(&array[i], &array[length-1]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: