首页 / 算法 / 【转】全排列算法非递归实现和递归实现
【转】全排列算法非递归实现和递归实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【转】全排列算法非递归实现和递归实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5475字,纯文字阅读大概需要8分钟。
内容图文
![【转】全排列算法非递归实现和递归实现](/upload/InfoBanner/zyjiaocheng/1070/89da6e12e9eb4215886f75968d8cd0dd.jpg)
来源:http://blog.csdn.net/e3399/article/details/7543861
(一)递归的全排列算法
(A、B、C、D)的全排列为
1、A后面跟(B、C、D)的全排列
2、B后面跟(A、C、D)的全排列
3、C后面跟(A、B、D)的全排列
4、D后面跟(A、B、C)的全排列
而对1中的(B、C、D)照样可以按照上面的形式进行分解。
1 /* ********************************************************************* 2 * Compiler: GCC 3 * Last Update: Mon 07 May 2012 07:08:58 PM CST 4 * File Name: 1.cpp 5 * Description: 利用stl中的next_permutation进行全排列 6 *********************************************************************** */ 7 #include <iostream> 8usingnamespace std; 910 template<typename T> 11void permutation(T array[], int begin, int end) 12{ 13int i; 1415if(begin == end){ 16for(i = 0; i <= end; ++i){ 17 cout<<array[i]<<""; 18 } 19 cout<<endl; 20return; 21 } else { 22//for循环遍历该排列中第一个位置的所有可能情况23for(i = begin; i <= end; ++i) { 24 swap(array[i], array[begin]); 25 permutation(array, begin + 1, end); 26 swap(array[i], array[begin]); 27 } 28 } 29} 3031int main(int argc, char **argv) 32{ 33int a[4] = {1, 2, 3, 4}; 34 permutation(a, 0, sizeof(a) / sizeof(int) - 1); 3536return0; 37 }
(二)非递归全排列算法,即按字典序排列算法。
基本思想是:
1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin。
2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。
3.循环执行第二步,直到找到一个最大的排列,算法结束。
如排列ABCDE,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:ABCED。
算法如下:
给定已知序列P
= A1A2A3.....An
对P按字典排序,得到P的一个最小排列Pmin = A1A2A3....An ,满足Ai > A(i-1)
(1 < i <=
n)
从Pmin开始,找到刚好比Pmin大的一个排列P(min+1),再找到刚好比P(min+1)大的一个排列,如此重复。
1.从后向前(即从An->A1),找到第一对为升序的相邻元素,即Ai
< A(i+1)。
若找不到这样的Ai,说明已经找到最后一个全排列,可以返回了。
2.从后向前,找到第一个比Ai大的数Aj,交换Ai和Aj。
3.将排列中A(i+1)A(i+2)....An这个序列的数逆序倒置,即An.....A(i+2)A(i+1)。因为由前面第1、2可以得知,A(i+1)>=A(i+2)>=.....>=An,这为一个升序序列,应将该序列逆序倒置,所得到的新排列才刚刚好比上个排列大。
4.重复步骤1-3,直到返回。
这个算法是C++ STL算法next_permutation的思想。
1 /* ********************************************************************* 2 * Compiler: GCC 3 * Last Update: Mon 07 May 2012 07:08:58 PM CST 4 * File Name: 1.cpp 5 * Description: 6 *********************************************************************** */ 7 #include <iostream> 8 #include <cstring> 9usingnamespace std; 1011//交换数组a中下标为i和j的两个元素的值12void swap(int *a,int i,int j) 13{ 14 a[i]^=a[j]; 15 a[j]^=a[i]; 16 a[i]^=a[j]; 17} 1819//将数组a中的下标i到下标j之间的所有元素逆序倒置20void reverse(int a[],int i,int j) 21{ 22for(; i<j; ++i,--j) { 23 swap(a,i,j); 24 } 25} 2627void print(int a[],int length) 28{ 29for(int i=0; i<length; ++i) 30 cout<<a[i]<<""; 31 cout<<endl; 32} 3334//求取全排列,打印结果35void combination(int a[],int length) 36{ 37if(length<2) return; 3839bool end=false; 40while(true) { 41 print(a,length); 4243int i,j; 44//找到不符合趋势的元素的下标i45for(i=length-2; i>=0; --i) { 46if(a[i]<a[i+1]) break; 47elseif(i==0) return; 48 } 4950for(j=length-1; j>i; --j) { 51if(a[j]>a[i]) break; 52 } 5354 swap(a,i,j); 55 reverse(a,i+1,length-1); 56 } 57} 58int main(int argc, char **argv) 59{ 60int a[4] = {1, 2, 3, 4}; 61 combination(a, sizeof(a) / sizeof(int)); 6263return0; 64 }
用STL实现:
STL有一个函数next_permutation(),它的作用是如果对于一个序列,存在按照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。
1 /* ********************************************************************* 2 * Compiler: GCC 3 * Last Update: Mon 07 May 2012 07:08:58 PM CST 4 * File Name: 1.cpp 5 * Description: 利用stl中的next_permutation进行全排列 6 *********************************************************************** */ 7 #include <iostream> 8 #include <algorithm> 9usingnamespace std; 1011 template <typename BidirectionalIterator> 12void permutation(BidirectionalIterator array, int len) 13{ 14 sort(array, array + len); 15do{ 16for(int i = 0; i < len; ++i){ 17 cout<<array[i]<<""; 18 } 19 cout<<endl; 20 }while(next_permutation(array, array + len)); 21} 2223int main(int argc, char **argv) 24{ 25int a[4] = {1, 2, 3, 4}; 26 permutation(a, sizeof(a) / sizeof(int)); 2728return0; 29 }
文章参考来源:http://blog.csdn.net/hackbuteer1/article/details/6657435
http://plutoblog.iteye.com/blog/976216
http://blog.csdn.net/aipb2008/article/details/2227490
有一定约束条件的全排列
http://blog.csdn.net/hackbuteer1/article/details/6657435
对数1,2,3,4,5要实现全排序。要求4必须在3的左边,其它的数位置随意。
思路:首先使用上面的2种方法之一实现全排列,然后对全排列进行筛选,筛选出4在3左边的排列。
1 #include "iostream" 2 #include "algorithm" 3usingnamespace std; 4 5void permutation(int* a,int length) 6{ 7int i,flag; 8 sort(a,a+length); 9do10 { 11for(i=0;i<length;i++) 12 { 13if(a[i]==3) 14 flag=1; 15elseif(a[i]==4) //如果3在4的左边,执行完代码,flag就是216 flag=2; 17 } 18if(flag==1) //如果4在3的左边,执行完代码,flag就是119 { 20for(i=0;i<length;i++) 21 cout<<a[i]; 22 cout<<endl; 23 } 24 }while(next_permutation(a,a+length)); 2526} 27int main(void) 28{ 29int i,a[5]; 30for(i=0;i<5;i++) 31 a[i]=i+1; 32 printf("%d以内所有4在3左边的全排列结果为:\n",i); 33 permutation(a,5); 34 system("pause"); 35return0; 36 }
下面的分析来自C语言程序设计-顾志华:(page251)
对一组数穷尽所有排列,还有更好的方法。将一个排列看成一个长整数,则每个排列对应一个不同的长整数,所有可能的排列对应着一组有限的整数。将这组整数按从小到大的顺序排成一个数列,从对应最小的整数开始,按数列的递增顺序顺序逐一列举每个排列对应的每一个整数,这能更有效地完成排列的穷举。从一个排列找出对应数列的下一个排列可在当前排列的基础上作部分调整来实现。倘若当前排列为1、2、4、8、7、6、5、3,并令其对应的长整数为12487653。要寻找比长整数12487653更大的排列,可从该排列的最后一个数字顺序向前逐位考察,当发现排列中的某个数字比前一个数字大时,如本例中的8比它的前一个数字4大,这说明还有对应更大整数的排列。但为了顺序从小到大列举出所有的排列,不能立即调整的太大,如本例中将数字8与4交换得到的序列12847653就不是排列12487653的下一个序列。为得到排列12487653的下一个排列,应从已考察过的那部分数字中选出比数字4大,但又是它们中最小的那一个数字,比如数字5,该数字也是从后向前考察过程中第一个比4大的数字。5与4交换后,得到排列12587643,在前面数字1、2、5固定的情况下,还应选择对应最小整数的那个序列。为此还需将后面那部分数字的排列顺序颠倒,如将数字8、7、6、4、3的顺序颠倒,得到排列1、2、5、3、4、6、7、8,这才是排列1、2、4、8、7、6、5、3的下一个排列。
原文:http://www.cnblogs.com/huashanqingzhu/p/3571089.html
内容总结
以上是互联网集市为您收集整理的【转】全排列算法非递归实现和递归实现全部内容,希望文章能够帮你解决【转】全排列算法非递归实现和递归实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。