全排列 c++实现

全排列就是指n个元素随机组合,不重复的所有排列方式,如{1,2,3}就有123,132,213,231,312,321一共6种排列方式。

常见的算法实现分为 递归 和 非递归 ,这里我们用一个例子来辅助说明。{1,2,3,4}

 

递归的实现:递归是一种优雅的思想,层层推进。首先,我们知道要实现1,2,3,4的全排列,每个数都会在第1个位置出现,那我们先固定第1位是1,而后我们要做的就是对后面的3位子序列进行全排列,这时固定子序列的第一位为2。 依此类推,直到子序列只剩1位,返回。画个简图帮助理解。

c++实现

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 //打印数组全部元素
 6 void prt(int arr[],int end){
 7     for(int i=0;i<=end;++i){
 8             printf("%d",arr[i]);
 9     }
10 }
11 
12 void perm(int arr[],int begin,int end){
13     if(begin==end){
14         prt(arr,end);
15         printf("\n");
16         return;
17     }
18     for(int i=begin;i<=end;++i){
19         swap(arr[begin],arr[i]);  //交换两个元素值
20         perm(arr,begin+1,end);
21         swap(arr[begin],arr[i]);
22     }
23 }

 

非递归的实现:这里采用的是字典序的方式生成全排列,1,2,3,4这4个数,组成形如1234,1243等序列,这些序列中1234最小,4321最大,由此我们从1234开始(或者4321也行),寻找第一个比1234大的序列,是1243;再寻找第一个比1243大的序列,是1324........依此类推,求出所有序列。

  具体实现:从右向左开始,找到第一个这样的数A(n-1)<A(n),从A(n)向右找最后一个比A(n-1)大的数A(m),交换A(n-1)和A(m),将A(n)到末尾所有元素逆序。重复上述步骤直到第一个元素。

c++实现:

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 void perm(int arr[],int len){
 6     if(len<2) return;
 7     int i,j,temp;
 8     do{
 9                 //输出当前序列
10         prt(arr,len-1);
11         printf("\n");
12         i=j=len-1;
13                 //向前查找第一个变小的元素
14         while(i>0&&arr[i]<arr[i-1]) --i;
15         temp=i;
16         if(i==0) break;
17                 //先后查找第一个比arr[i-1]大的元素
18         while(temp+1<len&&arr[temp+1]>arr[i-1]) ++temp;
19         swap(arr[i-1],arr[temp]);  //交换两个值
20         reverse(arr+i,arr+len);  //逆序
21     }while(true);
22 }

 

 

  

posted @ 2019-03-09 15:51  潇潇雨歇zhj  阅读(11032)  评论(0编辑  收藏  举报