字典法求全排列(非递归的方法)

【字典序法生成全排列】

字典序列算法是一种非递归算法。而它正是STL中Next_permutation的实现算法。我们来看看他的思路吧:
它的整体思想是让排列成为可递推的数列,也就是说从前一状态的排列,可以推出一种新的状态,直到最终状态。比如说,最初状态是12345,最终状态是54321。其实我觉得这跟我们手动做全排列是一样的。首先是12345,然后12354,然后12435,12453....逐渐地从后往前递增。
看看算法描述:
    首先,将待排序列变成有序(升序)序列。然后,从最后向前寻找,让相邻的两个元素比较大小 ,i = n-2,j=i+1,比较 Ti与Tj,如果没有找到 Ti<Tj,则说明整个序列已经是降序排列了,也就是说到达最终状态54321了。此时,全排列结束。

   如果找到 Ti<Tj,记录i的大小也就是Ti的位置

    然后,从数组最后向前找到第一个元素Tk,使得Tk>Ti(很多时候k=j),找到它,交换Ti跟Tk,并且将Tj到Tn-1(Tn-1是最后一个元素)的子序列进行倒置操作(也就是是Ti后面的序列全部进行翻转)。输出此序列。并回到第二步继续寻找i和k.
例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4    839647521
在该数字后的数字中找出比4大的数中第一个数是5    839647521
将5与4交换 839657421
将7421倒转 839651247
所以839647521的下一个排列是839651247。
839651247的下一个排列是839651274。

这里边的重点或者说是中心思想应该是:

1:两次查找--->分别得到要交换的Ai和Ak

2:两次交换----->第一次是将Ai和Ak 交换位置;

                        第二次是将下标为i的后面的元素顺序进行翻转


代码如下:

	#include <stdio.h>   
	#include <stdlib.h>   
	   
	//function definition   
	void Swap(int &a,int &b);   
	void Reverse (int[],int,int);   
	void printArray (int[],int);   
	   
	int nextPermutation(int[],int);   
	   
   
	void Swap(int &a,int &b){   
	    int tmp;   
	    tmp=a;   
	    a=b;   
	    b=tmp;   
	}   
	   
	void Reverse(int target[],int begin,int end){   
	       
	    while (begin<end){   
	        Swap(target[begin],target[end]);   
	        begin++;   
	        end--;   
	    }   
	   
	}   
	   
	//function implementation   
	int nextPermutation(int target[],int end){   
	       
	    int i =3,j =3;   
	    for (i=end-1;i>=0;i--){   
	        if (target[i]<target[i+1]) break;  
         } 
	       
	    if (i<0) return 0; //means the permutation is over   
	   
	    j=i+1;   
	   
	    int k;   
	    for (k=end;target[k]<=target[i];k--);   
	       
	    Swap(target[i],target[k]);   
	    Reverse(target,j,end);   
	    return 1;   
	}    
	   
	void printArray (int target[],int length){   
	    int i;   
	    for (i=0;i<length;i++) printf ("%d-",target[i]);   
	    printf ("\n");   
	}   
	   
	//test function   
	void testPermute(){   
	    printf ("input a number:");   
	    int n;   
	    scanf ("%d",&n);   
	    int i;   
	    int * testcase = (int*)malloc(n*sizeof(int));   
	    for (i=0;i<n;i++) testcase[i]=i+1;   
	    printArray (testcase,n);   
	    while (nextPermutation(testcase,n-1)){   
	        printArray (testcase,n);   
	    }   
	}   
	   
	//main function   
	int main(){   
	   
	    testPermute();  
        system("pause");
        return 0; 
	}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值