字典序全排列简单研究

最近看算法设计与分析基础这本书,里面讲到了一个字典序全排列问题,书中的方法是:
(1)从右至左扫描当前的一个排列,需找第一个连续的选择ai和ai+1,使得ai<ai+1。
(2)在尾部存在大于ai的最小数也就是min{aj | aj>ai, j>i},并将它放置在i位置上。
(3)从i+1到n的位置,以元素ai,ai+1,....an.的增序进行填充,其中放在位置i上的元素已经消去。
这个方法也就是字典序非递归法,更简单的描述是:
 一般而言,设P是[1,n]的一个全排列。
      P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn
    find:  j=max{i|Pi<Pi+1}
             k=max{i|Pi>Pj}
      1,  对换Pj,Pk,
      2,  将Pj+1…Pk-1PjPk+1…Pn翻转
              P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个

确实很巧妙的算法了,算法复杂度为O(n*n!)
我自己也小试牛刀一把,实现了下字典序最基本的递归算法。思路图大致如下
即定义一个isUsed数组,标记1~n数是否使用,在定义一个arr数组,按从小到大顺序存放第 i 位应该存放的数字。当isUsed数组全部标记使用时,输出当前arr数组。
每次从小到大填充arr数组时,从小到大遍历isUsed数组,选出第一个未标记使用的数字,存放到arr数组,并标记isUsed使用,然后arr数组下一位数字的填充(递归)。
算法复杂度为O((n!)^2)
代码如下:
#include <stdio.h>

#define N_MAX 100

void fun(int N, int *isUsed, int k, int *arr)
{
	int i=0,j=0;
	static int num=0;
	for(i=0;i<N;i++)
	{
		if(isUsed[i]!=0)
			continue;

		*(arr+k)=i+1;
		isUsed[i]=1;

		if(k >= (N-1))
		{
			printf("arr %d: ",++num);
			for(j=0;j<N;j++)
				printf(" %d",arr[j]);
			printf("\n");
		}
		else
			fun(N,isUsed,k+1,arr);

		isUsed[i]=0;
	}

}

void main()
{
	int isUsed[N_MAX]={0};
	int arr[N_MAX]={0};
	int k=0,n=5;

	fun(n,isUsed,k,arr);
}

如参考1中所说,如果要提高性能,可采用并行计算 + nmap将文件映射到内存。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值