首页 > 代码库 > 排列组合递归和非递归算法总结篇
排列组合递归和非递归算法总结篇
#include <iostream> #include <string> #include <math.h> #include <vector> #include <algorithm> using namespace std; //method1 bool flag[5] ; int arr[5] = {1,2,3,4,5}; int len = sizeof(arr)/sizeof(int); void Comb(int n,int count); // //method2 void Comb2(int n,int count); vector<int> result; //method3: void Comb3(int n,int count); int GetCombCount(int n,int m); //3 void GetCharComb(); //4 int data[3] = {1,2,3}; int data1[3] = {4,2,3}; void permutation(int *a,int len); void stl_permutaton(int *a,int len); //求全幂集 可以依次取Comb(4,1) Comb(4,2) Comb(4,5) + 空集 //5 int num = 0; void permutation(int array[], int begin, int end); int main() { vector<char> result; for(int i = 0;i<5;i++) flag[i] = false; cout << "---递归组合1(根据标志位打印每一个组合)----" << endl; Comb(4,3); cout << "---递归组合2(保存每一个组合到容器中)---" << endl; Comb2(4,1); cout << "---非递归组合---" << endl; Comb3(5,3); cout << "---字符串所有组合(幂集除去空串)----" << endl; GetCharComb(); cout << "---非递归排列---" << endl; permutation(data,3); cout << "----STL全排列--" << endl; stl_permutaton(data1,3); cout <<"--递归排列----" << endl; int a[3] = { 2, 3, 4}; permutation(a, 0, sizeof(a) / sizeof(int) - 1); return 0; } void Comb(int n,int count) { if(count == 0) { //simiar with select using vector storage selected data will be similar with epoll for(int i = 0;i<len;i++) if(flag[i] == true) cout << arr[i] << " "; cout << endl; return;//- exit condition 1--(递归结束条件1) } if(n<0)// exit condition 2 --(递归结束条件2) return; flag[n] = true; Comb(n-1,count-1); flag[n] = false; Comb(n-1,count); } void Comb2(int n,int count) { if(count == 0) { //每次递归结束 求得的一个组合 , vector<int>::iterator it; for(it = result.begin();it < result.end();it++)// cout << *it << " "; cout << endl; return; } if(n<0) return; result.push_back(arr[n]); Comb2(n-1,count-1); result.pop_back(); Comb2(n-1,count); } /* 用一个数组,模拟2进制加法器,某一个为1,则取对应的字符,若为0则不取,就能够实现字符组合。也可以不用数组。设有n个字符。 int num 从 1 自增到 2^n -1, 将num右移i位,跟1做按位&操作,即可判断第i个字符取还是不取。 001 010 011 100 101 110 111 c b bc a ac ab abc //还存在的问题的是符数组的长度<32的话这个办法还是很不错的,如果>32就需要原始方法了。 */ void GetCharComb() {//求幂集 //string str= "aabc"; string str = "abc"; int N = str.size(); int num = pow(2.0,N) ;// (2.0 N) for(int i=1;i<num;i++)//num = [1-7] { for(int j=0;j<N;j++) { if((i>>j)&1)//tips ----:检测为1的bit位 cout<<str[j];//----str[j] 则先为a } cout<<endl; } } /* 字典序变化(1234----> 4321) 1.从最右边开始比较两两相邻的元素,直至找到右边比左边大的一对,左边那个 2.就是将要被替换的,再从最右边开始找比这个元素大的第一个,交换他们两个 3.交换之后,翻转交换元素的后面的所有元素 */ void permutation(int *a,int len) { int i,j; int tmp; int num = 6;//1*2*3 copy(arr,arr+len,ostream_iterator<int,char>(cout," ")); cout << endl; for(i=len-1;i>0;i--) { if(a[i] > a[i-1])// i-1 【1】 { for(j = len-1;j>=0;j--) if(a[j] > a[i-1])//【2】 { tmp = a[i-1]; a[i-1] = a[j]; a[j] = tmp; //【3】 int m = i,n = len-1; while(m<=n) { tmp = a[m]; a[m] = a[n]; a[n] = tmp; m++; n--; } break; } i = len;//begin again copy(a,a+len,ostream_iterator<int,char>(cout," ")); cout << endl; } } } void stl_permutaton(int *a,int len) {//字典序的第一个序列必须递增 sort(a,a+len); do { copy(a,a+len,ostream_iterator<int,char>(cout," ")); cout << endl; }while(next_permutation(a,a+len)); } /* 思路: (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)照样可以按照上面的形式进行分解。 */ void permutation(int array[], int begin, int end) { int i; if(begin == end){//递归退出条件 处理最后一个元素了 num ++; //cout << end << endl; for(i = 0; i <= end; ++i){ cout<<array[i]<<" "; } cout<<endl; return; } else { //for循环遍历该排列中第一个位置的所有可能情况 for(i = begin; i <= end; ++i) { swap(array[i], array[begin]); permutation(array, begin + 1, end); swap(array[i], array[begin]);//还原数组 继续下一次遍历 } } } //Non-Recursive method to get combination void Comb3(int n,int count) {/* 递减最小变化: 从右往左找第一对10交换,表示我想把数变小 但我我希望减小的最少,则交换点后面的数要尽量大,所以把1全部移到交换点后的高位 11100 11010 11001 10110 10101 10011 01110 01101 01011 00111 */ //int bit[5] = {1,1,1,0,0};//initial bit array int *bit = new int[n]; for(int k = 0;k<n;k++) { if(k<count) bit[k] = 1; else bit[k] = 0; } int i,j,beg,end; int len = sizeof(arr)/sizeof(int); int N = GetCombCount(n,count); //C(n,count) C(5,3) for(i = 0;i<len;i++) if(bit[i] == 1) cout << arr[i]; cout << endl; for(j = 1;j<=N-1;j++) { for(i = len-1;i>0;i--) { if(bit[i] == 0 && bit[i-1] == 1) { swap(bit[i],bit[i-1]); //from index: [i to len-1] , make all bit 1 in the right beg = i; end = len - 1; while(1) { while(bit[beg] == 1) { beg ++; if(beg >= len) break; } while(bit[end] == 0) { end --; if(end <i) break; } if(beg < end) swap(bit[beg],bit[end]); else break; }//end of "while" break; }//end of "if" // copy(bit,bit+5,ostream_iterator<int,char>(cout," ")); // cout <<endl; } for(i = 0;i<len;i++) if(bit[i] == 1) cout << arr[i]; cout << endl; } } int GetCombCount(int n,int m) { int i; int a,b,c,s;// s = a/(b*c) a = b = c =1; for(i = 1;i<=n;i++) a*=i; for(i = 1;i<=m;i++) b*=i; for(i = 1;i<=n-m;i++) c*=i; s = a/(b*c); return s; }
排列组合递归和非递归算法总结篇
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。