排列組合遞迴和非遞迴演算法總結篇,排列組合遞迴演算法
#include <iostream>#include <string>#include <math.h>#include <vector>#include <algorithm>using namespace std;//method1bool flag[5] ;int arr[5] = {1,2,3,4,5};int len = sizeof(arr)/sizeof(int);void Comb(int n,int count);////method2void Comb2(int n,int count);vector<int> result;//method3:void Comb3(int n,int count);int GetCombCount(int n,int m);//3void GetCharComb();//4int 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) + 空集//5int 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 111c 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*3copy(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 againcopy(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 combinationvoid Comb3(int n,int count){/*遞減最小變化:從右往左找第一對10交換,表示我想把數變小但我我希望減小的最少,則交換點後面的數要盡量大,所以把1全部移到交換點後的高位11100110101100110110101011001101110011010101100111 *///int bit[5] = {1,1,1,0,0};//initial bit arrayint *bit = new int[n];for(int k = 0;k<n;k++){if(k<count)bit[k] = 1;elsebit[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 rightbeg = 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]);elsebreak;}//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;}
用遞迴實現排列組合問題
只講A的 C的同理
跟階層一樣,
int f(int n)
static int s;
if(n>1)
{s*=n;
return f(n-1); }
else
return s;
若不是An,n
你就定義條件
這個vb演算法怎實現?(可可以用到排列組合跟遞迴)助
這實際上是一個排列組合裡的分步法。下面的代碼是用遞迴法來求,供參考:
Sub main()Dim srcTxt$, myAry(), tmp, UB%'------未經處理資料輸入到數組-----------srcTxt = "cap,tat,nbc-abc,mnt,xxs-oop"tmp = Split(srcTxt, "-")UB = UBound(tmp)ReDim myAry(UB)For i = 0 To UBmyAry(i) = Split(tmp(i), ",")Next i'----調用遞迴求組合------Dim x%, p(), PM(), pNo&ReDim p(UB)GetPmt x, p(), pNo, PM(), myAry()'--------輸出---------MsgBox "可能的組合有:" & vbCrLf & vbCrLf & Join(PM, vbCrLf), vbInformationEnd Sub''遞迴求組合,並將結果放入PM()數組Sub GetPmt(ByVal x%, p(), pNo&, PM(), myAry())For i = 0 To UBound(myAry(x))p(x) = myAry(x)(i)If x = UBound(myAry) ThenReDim Preserve PM(pNo)PM(pNo) = Join(p, " ")pNo = pNo + 1ElseGetPmt x + 1, p(), pNo, PM(), myAry()End IfNext iEnd Sub