日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

算法之排列与组合算法

發(fā)布時(shí)間:2025/6/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法之排列与组合算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1. 前言

本文介紹了常用的排列組合算法,包括全排列算法,全組合算法,m個(gè)數(shù)選n個(gè)組合算法等。

2. 排列算法

常見(jiàn)的排列算法有:

(A)字典序法

(B)遞增進(jìn)位制數(shù)法

(C)遞減進(jìn)位制數(shù)法

(D)鄰位對(duì)換法

(E)遞歸法

介紹常用的兩種

(1) 字典序法

對(duì)給定的字符集中的字符規(guī)定了一個(gè)先后關(guān)系,在此基礎(chǔ)上按照順序依次產(chǎn)生每個(gè)排列。

[例]字符集{1,2,3},較小的數(shù)字較先,這樣按字典序生成的全排列是:123,132,213,231,312,321。

生成給定全排列的下一個(gè)排列 所謂一個(gè)的下一個(gè)就是這一個(gè)與下一個(gè)之間沒(méi)有字典順序中相鄰的字符串。這就要求這一個(gè)與下一個(gè)有盡可能長(zhǎng)的共同前綴,也即變化限制在盡可能短的后綴上。

算法思想

設(shè)P是[1,n]的一個(gè)全排列。

P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn , j=max{i|Pi<Pi+1}, k=max{i|Pi>Pj} ,對(duì)換Pj,Pk,將Pj+1…Pk-1PjPk+1…Pn翻轉(zhuǎn), P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一個(gè)

例子:839647521的下一個(gè)排列.

從最右開(kāi)始,找到第一個(gè)比右邊小的數(shù)字4(因?yàn)?<7,而7>5>2>1),再?gòu)淖钣议_(kāi)始,找到4右邊比4大的數(shù)字5(因?yàn)?>2>1而4<5),交換4、5,此時(shí)5右邊為7421,倒置為1247,即得下一個(gè)排列:839651247.用此方法寫(xiě)出全排列的非遞歸算法如下

該方法支持?jǐn)?shù)據(jù)重復(fù),且在C++ STL中被采用。

(2) 遞歸法

設(shè)一組數(shù)p = {r1, r2, r3, … ,rn}, 全排列為perm(p),pn = p – {rn}。則perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), … , rnperm(pn)。當(dāng)n = 1時(shí)perm(p} = r1。

如:求{1, 2, 3, 4, 5}的全排列

1、首先看最后兩個(gè)數(shù)4, 5。 它們的全排列為4 5和5 4, 即以4開(kāi)頭的5的全排列和以5開(kāi)頭的4的全排列。

由于一個(gè)數(shù)的全排列就是其本身,從而得到以上結(jié)果。

2、再看后三個(gè)數(shù)3, 4, 5。它們的全排列為3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六組數(shù)。

即以3開(kāi)頭的和4,5的全排列的組合、以4開(kāi)頭的和3,5的全排列的組合和以5開(kāi)頭的和3,4的全排列的組合.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <stdio.h> int n = 0; void swap(int *a, int *b) { ??int m; ??m = *a; ??*a = *b; ??*b = m; } void perm(int list[], int k, int m) { ??int i; ??if(k > m) ??{ ????for(i = 0; i <= m; i++) ??????printf("%d ", list[i]); ????printf("\n"); ????n++; ??} ??else ??{ ????for(i = k; i <= m; i++) ????{ ??????swap(&list[k], &list[i]); ??????perm(list, k + 1, m); ??????swap(&list[k], &list[i]); ????} ??} } int main() { ??int list[] = {1, 2, 3, 4, 5}; ??perm(list, 0, 4); ??printf("total:%d\n", n); ??return 0; }

3. 組合算法

3.1 全組合

在此介紹二進(jìn)制轉(zhuǎn)化法,即,將每個(gè)組合與一個(gè)二進(jìn)制數(shù)對(duì)應(yīng)起來(lái),枚舉二進(jìn)制的同時(shí),枚舉每個(gè)組合。如字符串:abcde

00000 <– –> null

00001<– –> e

00010 <– –> d

… …

11111 <– –> abcde

3.2 從n中選m個(gè)數(shù)

(1) 遞歸

a. 首先從n個(gè)數(shù)中選取編號(hào)最大的數(shù),然后在剩下的n-1個(gè)數(shù)里面選取m-1個(gè)數(shù),直到從n-(m-1)個(gè)數(shù)中選取1個(gè)數(shù)為止。

b. 從n個(gè)數(shù)中選取編號(hào)次小的一個(gè)數(shù),繼續(xù)執(zhí)行1步,直到當(dāng)前可選編號(hào)最大的數(shù)為m。

下面是遞歸方法的實(shí)現(xiàn):

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 /// 求從數(shù)組a[1..n]中任選m個(gè)元素的所有組合。 /// a[1..n]表示候選集,n為候選集大小,n>=m>0。 /// b[1..M]用來(lái)存儲(chǔ)當(dāng)前組合中的元素(這里存儲(chǔ)的是元素下標(biāo)), /// 常量M表示滿(mǎn)足條件的一個(gè)組合中元素的個(gè)數(shù),M=m,這兩個(gè)參數(shù)僅用來(lái)輸出結(jié)果。 void combine( int a[], int n, int m,? int b[], const int M ) { ??for(int i=n; i>=m; i--)?? // 注意這里的循環(huán)范圍 ??{ ????b[m-1] = i - 1; ????if (m > 1) ??????combine(a,i-1,m-1,b,M); ????else???????????????????? // m == 1, 輸出一個(gè)組合 ????{ ??????for(int j=M-1; j>=0; j--) ??????cout << a[b[j]] << " "; ??????cout << endl; ????} ??} }

(2) 01轉(zhuǎn)換法

本程序的思路是開(kāi)一個(gè)數(shù)組,其下標(biāo)表示1到n個(gè)數(shù),數(shù)組元素的值為1表示其代表的數(shù)被選中,為0則沒(méi)選中。

首先初始化,將數(shù)組前n個(gè)元素置1,表示第一個(gè)組合為前n個(gè)數(shù)。

然后從左到右掃描數(shù)組元素值的“10”組合,找到第一個(gè)“10”組合后將其變?yōu)椤?1”組合,同時(shí)將其左邊的所有“1”全部移動(dòng)到數(shù)組的最左端。

當(dāng)?shù)谝粋€(gè)“1”移動(dòng)到數(shù)組的n-m的位置,即n個(gè)“1”全部移動(dòng)到最右端時(shí),就得到了最后一個(gè)組合。

例如求5中選3的組合:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 1 1 0 0 //1,2,3 1 1 0 1 0 //1,2,4 1 0 1 1 0 //1,3,4 0 1 1 1 0 //2,3,4 1 1 0 0 1 //1,2,5 1 0 1 0 1 //1,3,5 0 1 1 0 1 //2,3,5 1 0 0 1 1 //1,4,5 0 1 0 1 1 //2,4,5 0 0 1 1 1 //3,4,5

4. 參考資料

(1) http://www.cnblogs.com/nokiaguy/archive/2008/05/11/1191914.html

(2) http://comic.sjtu.edu.cn/thucs/GD_jsj_025y/text/chapter01/sec05/default.htm

(3) http://blog.csdn.net/sharpdew/archive/2006/05/25/755074.aspx

(4) http://xiaomage.blog.51cto.com/293990/74094

總結(jié)

以上是生活随笔為你收集整理的算法之排列与组合算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。