167 请编程实现全排列算法

67、请编程实现全排列算法。
全排列算法有两个比较常见的实现:递归排列和字典序排列。

/*
67、请编程实现全排列算法。
全排列算法有两个比较常见的实现:递归排列和字典序排列。

(1)递归实现
从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,
如此递归处理,从而得到所有元素的全排列.

(2)字典序排列
思想是让排列成为可递推的数列,也就是说从前一状态的排列,可以推出一种新的状态,直到最终状态。
比如说,最初状态是12345,最终状态是54321。首先是12345,然后12354,然后12435,12453....逐渐地从后往前递增。

算法:
    首先,将待排序列变成有序(升序)序列。然后,从后向前寻找,找到相邻的两个元素,Ti<Tj(j=i+1)。
如果没有找到,则说明整个序列已经是降序排列了,也就是说到达最终状态54321了。此时,全排列结束。

    接着,如果没有结束,从后向前找到第一个元素Tk,使得Tk>Ti(很多时候k=j),找到它,交换Ti跟Tk,
并且将Tj到Tn(Tn是最后一个元素)的子序列进行倒置操作。
输出此序列。并回到第二步继续寻找ij.

例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4    839647521
在该数字后的数字中找出比4大的数中最小的一个5    839647521
将5与4交换 839657421
将7421倒转 839651247
所以839647521的下一个排列是839651247。
839651247的下一个排列是839651274。

递归实现版本在优化情况下要慢很多,主要原因可能在于太多的函数调用开销,
但在不优化情况下执行比其它二个版本要快,原因可能在于程序结构更简单,执行的语句较少。
比较而言,递归算法结构简单,适用于全部计算出所有的排列(因此排列规模不能太大,计算机资源会成为限制);
而字典序排列逐个产生、处理排列,能够适用于大的排列空间,并且它产生的排列的规律性很强。

*/
#include<iostream> 
#include<stdio.h>
#include<algorithm> 
using namespace std; 
//template <typename T>
int k,n=4;

//递归 
void rankRuc(char perm[],int n,int index)  
{ 
	if(index==n)  
    {  
    	printf("%2d:",k++); 
        for(int i=0;i<n;i++)  
            printf("%c",perm[i]);  
        printf("\n");  
        return ;  
    }  	
	for (int i=index;i<n;++i) 
	{ 
		swap(perm[i],perm[index]); 
		rankRuc(perm,n,index+1);   
		swap(perm[i], perm[index]); 
	} 
} 
//字典序 
void rankDic(char perm[],int num) 
{ 
	int i,k;
	
	if (num<1)
		return;
				 
	while(true)
	{ 
		for (i=num-2;i>=0;--i)
			if (perm[i]<perm[i+1]) 
				break; 
		if (i<0) 
			break;  // 已经找到所有排列
			
		for(k=num-1;k>i;--k) 
			if(perm[k]>perm[i]) 
				break; 
		swap(perm[i],perm[k]);
		reverse(perm +i+1,perm+num); 
		
        for(int i=0;i<n;i++)  
            printf("%c",perm[i]);  
        printf("\n"); 
	} 
}

int main() 
{ 
	char perm[]={"abcd"}; 
	k=1;
	rankRuc(perm,4,0); //24个 
	
	printf("字典序排列:\n"); 
	rankDic(perm,4); //24个 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值