全排列表示把集合中元素的所有按照一定的順序排列起來,使用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 全部移動到陣列的最左端。當第...