C語言實現的排列組合問題的通用演算法 解決方法

2022-10-04 04:15:07 字數 2462 閱讀 9685

儘管排列組合是生活中經常遇到的問題,可在程式設計時,不深入思考或者經驗不足都讓人無從下手。由於排列組合問題總是先取組合再排列,並且單純的排列問題相對簡單,所以本文僅對組合問題的實現進行詳細討論。以在n個數中選取m(0

1. 首先從n個數中選取編號最大的數,然後在剩下的n-1個數裡面選取m-1個數,直到從n-(m-1)個數中選取1個數為止。

2. 從n個數中選取編號次小的乙個數,繼續執行1步,直到當前可選編號最大的數為m。

很明顯,上ctvotr述方法是乙個遞迴的過程,也就是說用遞迴的方法可以很乾淨利索地求得所有組合。

下面是遞迴方法的實現:

複製** **如下:

/// 求從陣列a[1..n]中任選m個元素的所有組合。

/// a[1..n]表示候選集,n為候選集大小,n>=m>0。

/// b[1..m]用來儲存當前組合中的元素(這裡儲存的是元素下標),

/// 常量m表示滿足條件的乙個組合中元素的個數,m=m,這兩個引數僅用來輸出結果。

void combine( ictvotrnt a, int n, int m,  int b, const int m ) }}

因為遞迴程式均可以通過引入棧,用回溯轉化為相應的非遞迴程式,所以組合問題又可以用回溯的方法來解決。為了便於理解,我們可以把組合問題化歸為圖的路徑遍歷問題,在n個數中選取m個數的所有組合,相當於在乙個這樣的圖中(下面以從1,2,3,4中任選3個數為例說明)求從[1,1]位置出發到達[m,x](m<=x<=n)位置的所有路徑:

複製** **如下:

1  2  3  4

2  3  4

3  4

上圖是擷取nn右上對角矩陣的前m行構成,如果把矩矩中的每個元素看作圖中的乙個節點,我們要求的所有組合就相當於從第一行的第一列元素[1,1]出發,到第三行的任意一列元素作為結束的所有路徑,規定只有相鄰行之間的節點,並且下一行的節點必須處於上一行節點右面才有路徑相連,其他情況都無路徑相通。顯然,任一路徑經過的數字序列就對應乙個符合要求的組合。

下面是非遞迴的回溯方法的實現:

複製** **如下:

/// 求從陣列a[1..n]中任選m個元素的所有組合。

/// a[1..n]表示候選集,m表示乙個組合的元素個數。

/// 返回所有組合的總數。

int combine(int a, int n, int m)

order[k]++;                // 在當前位置選擇新的數字

if(order[k] == n)          // 當前位置已無數字可選,回溯

if(k < m)                  // 更新當前位置的下一位置的數字         

if(k == m)

flag = true;

} delete order;

return count;

}下面是測試以上函式的程式:

複製** **如下:

int main()

由上述分析可知,解決組合問題的通用演算法不外乎遞迴和回溯兩種。在針對具體問題的時候,因為遞迴程式在遞迴層數上的限制,對於大型組合問題而言,遞迴不是乙個好的選擇,這種情況下只能採取回溯的方法來解決。

n個數的全排列問題相對簡單,可以通過交換位置按序列舉來實現。stl提供了求某個序列下乙個排列的演算法next_permutation,其演算法原理如下:

1. 從當前序列最尾端開始往前尋找兩個相鄰元ctvotr素,令前面乙個元素為*i,後乙個元素為*ii,且滿足*i

2. 再次從當前序列末端開始向前掃瞄,找出第乙個大於*i的元素,令為*j(j可能等於ii),將i,j元素對調;

3. 將ii之後(含ii)的所有元素顛倒次序,這樣所得的排列即為當前序列的下乙個排列。

其實現**如下:

複製** **如下:

template

bool next_permutation(bidirectionaliterator first, bidirectionaliterator last)

if (i == first)                   // 進行至最前面了

}} 下面程式演示了利用next_permutation來求取某個序列全排列的方法:

複製** **如下:

int main()

; vector iv(ia,ia+sizeof(ia)/sizeof(int));

copy(iv.begin(),iv.end(),ostream_iterator(cout," "));

cout << endl;

while(next_permutation(iv.begin(),iv.end()))

return 0;

}注意:上面程式中初始序列是按數值的從小到大的順序排列的,如果初始序列無序的話,上面程式只能求出從當前序列開始的後續部分排列,也就是說next_permutation求出的排列是按排列從小到大的順序進行的。

本文標題: c語言實現的排列組合問題的通用演算法、解決方法

本文位址:

C語言實現排列組合

include include int array define n 4 define m 3 int results n 儲存已經找到的結果字首陣列 int results end 0 結果字首陣列有效資料下標 int is used n 是否已經排列過了的標誌 排列 param deep 遞迴深...

c語言實現排列組合

1.求排列組合結果總數 組合 採用遞迴演算法,根據下面第二行公式。k 排列 採用遞迴。思想來自 int sumpailie int n,int k 2.展示排列,組合結果。排列 首先從 n 個中取乙個數,再在剩餘的一次次取乙個數,每取乙個數就把這位標記為取過了,以免下次再取。取夠k個數之後,把k個數...

C語言實現排列組合(全排列)

題目描述 排列與組合是常用的數學方法。先給乙個正整數 1 n 10 例如n 3,所有組合,並且按字典序輸出 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 輸入 輸入乙個整數n 1 n 10 輸出 輸出所有全排列 每個全排列一行,相鄰兩個數用空格隔開 最後乙個數後面沒有空格 ...