排列組合演算法實現

2021-07-09 02:45:19 字數 3153 閱讀 4064

全排列表示把集合中元素的所有按照一定的順序排列起來,使用p(n, n) = n!表示n個元素全排列的個數。

例如:的全排列為:

123;

132;

213;

231;

312;

321;

共6個,即3!=321=6。

這個是怎麼算出來的呢?

首先取乙個元素,例如取出了1,那麼就還剩下。

然後再從剩下的集合中取出乙個元素,例如取出2,那麼還剩下。

以此類推,把所有可能的情況取一遍,就是全排列了,如圖:

演算法分析:

1)將陣列看為乙個集合,將集合分為兩部分:0~s和s~e,其中0~s表示已經選出來的元素,而s~e表示還沒有選擇的元素;

2)遞迴求解s-e中的全排列;

演算法實現:

//ilen:陣列長度

//istart:陣列下標,也即將集合分為兩半的s

// 0-------s-------e

// 0 1 2 3 4 5 6 7 8 9

// | |

// istart j

void fullarray(int a, int ilen, int istart) ;

void fullarray(int a, int ilen, int istart)

printf("\n");

}else}}

組合指從n個不同元素中取出m個元素來合成的乙個組,這個組內元素沒有順序。使用c(n, k)表示從n個元素中取出k個元素的取法數。

c(n, k) = n! / (k! * (n-k)!)

例如:從中取出2個元素的組合為:

12;

13;

14;

23;

24;

34 方法是:先從集合中取出乙個元素,例如取出1,則剩下

然後從剩下的集合中取出乙個元素,例如取出2

這時12就構成了乙個組,如圖。

演算法分析:

從上面這個過程可以看出,每一次從集合中選出乙個元素,然後對剩餘的集合(n-1)進行一次k-1組合。

comb(set, subset, n, k)

演算法實現:

void combine(int s,int n,int k,void(*cbk)(int* subset,int k))

for(int i = n; i >= k; i--)

else}}

首先來看一段**:

#include

#include

usingnamespace std;

int main ()

; cout

<

sort (myints,myints+3);

dowhile( next_permutation (myints,myints+3));

return

0;}

這段**是從stl permutation上考下來的,要注意的是第10行,首先對陣列進行了排序sort()

第14行的next_permutation()是stl的函式,它的原理是這樣的:生成當前列表的下乙個相鄰的字典序列表,裡面的元素只能交換位置,數值不能改變。

什麼意思呢?

123的下乙個字典序是132,因為132比123大,但是又比其他的序列小。

演算法分析:

(1) 從右向左,找出第乙個比右邊數字小的數字a。

(2) 從右向左,找出第乙個比a大的數字b。

(3) 交換a和b。

(4) 將a後面的串(不包括a)反轉。

演算法實現:寫出next_permutation函式:

templatebool next_perm(t * start, t * end)

if(start == end)

else

else

}if(pa == null)

pb = p;

break;}}

// swap a, b.

tmp =*pa;

*pa =*pb;

*pb = tmp;// flip sequence after a

for(t *p = pa+1,*q =end; p < q; p++, q--)

return true;}}

使用0或1表示集合中的元素是否出現在選出的集合中,因此乙個0/1列表即可表示選出哪些元素。

例如:[1 2 3 4 5],選出的元素是[1 2 3]那麼列表就是[1 1 1 0 0]。

演算法分析:

comb

(set, n, k)

演算法實現:

templatevoid combine(t set,int n,int k,void(*cbk)(t set))

// begin scan.

bool has_next =true;

while(has_next) // get choosen.

}cbk(subset);

has_next =false;

for(int i =0; i < n -1; i++)

if(count < i)

for(int j = count; j < i; j++)

}has_next =true;

break;}}

}delete vec;

delete subset;

}

至於其中的道理,n個位置上有k個1,按照演算法移動,可以保證k個1的位置不重複,且覆蓋n一遍。

排列組合演算法

在開發的過程中很難免會到排列組合,剛開始通過for迴圈來搞定。但是對於工作了近五年的我而已,不能像 新人那樣做了。如果所要組合的集合大於40,你不可能寫40個for迴圈吧!這裡使用了數學的演算法,到底是啥演算法,高人也沒說!不過我把它的思想提公升了一下。如下 ifndef combination h...

排列組合演算法

1.排列演算法 include define max num 100 void print int n,int num void swap int a,int b int arrange int i,int n,int num i return count int combination int u...

排列組合演算法

組合演算法的思路是開乙個陣列,其下標表示1到m個數,陣列元素的值為1表示其下標代表的數被選中,為0則沒選中。初始化,將陣列前n個元素置1,表示第乙個組合為前n個數。從左到右掃瞄陣列元素值的 10 組合,找到第乙個 10 組合後將其變為 01 組合,同時將其左邊的所有 1 全部移動到陣列的最左端。當第...