演算法設計 全排列遞迴

2022-02-25 14:58:21 字數 3027 閱讀 1655

排列:從n個元素中任取m個元素,並按照一定的順序進行排列,稱為排列;

全排列:當n==m時,稱為全排列;

比如:集合的全排列為:

我們可以將這個排列問題畫成圖形表示,即排列列舉樹,比如下圖為的排列列舉樹,此樹和我們這裡介紹的演算法完全一致;

演算法思路:

(1)n個元素的全排列=(n-1個元素的全排列)+(另乙個元素作為字首);

(2)出口:如果只有乙個元素的全排列,則說明已經排完,則輸出陣列;

(3)不斷將每個元素放作第乙個元素,然後將這個元素作為字首,並將其餘元素繼續全排列,等到出口,出口出去後還需要還原陣列;

這裡先把集合中的元素理解為不會出現重複了,那麼實現的方法(c++)如下:

成員管理,互評,檔案共享,事務通知

#include

using

namespace

std;

int sum = 0;//

記錄有多少種組合

void swap(char str, int a, int

b)void perm(char str, int begin, int

end)

cout

<

sum++;

return

; }

else

}}int

main()

perm(c,

0, n - 1

); }

cout

<

cout

<

return0;

}

實現後效果如下圖:

然後現在的題目要求是排列中的元素是包含相同元素的,給定n以及待排的n個可能重複的元素。計算輸出n個元素的所有不同排列,因此上面那個演算法顯然還是不夠好,因為相同的元素都當成不同的元素,因此有了重複的排列在裡面

去掉重複符號的全排列:在交換之前可以先判斷兩個符號是否相同,不相同才交換,這個時候需要乙個判斷符號是否相同的函式。也就是下面的isswap();

對122,第乙個數1與第二個數2交換得到212,然後考慮第乙個數1與第三個數2交換,此時由於第三個數等於第二個數,所以第乙個數不再與第三個數交換。再考慮212,它的第二個數與第三個數交換可以得到解決221。

去掉重複的規則:去重的全排列就是從第乙個數字起每個數分別與它後面非重複出現的數字交換。

#include using

namespace

std;

int sum=0;//

記錄有多少種組合

實現思路:

要考慮全排列的非遞迴實現,先來考慮如何計算字串的下乙個排列。如"1234"的下乙個排列就是"1243"。只要對字串反覆求出下乙個排列,全排列的也就迎刃而解了。

如何計算字串的下乙個排列了?來考慮"926520"這個字串,我們從後向前找第一雙相鄰的遞增數字,"20"、"52"都是非遞增的,"26 "即滿足要求,稱前乙個數字2為替換數,替換數的下標稱為替換點,再從後面找乙個比替換數大的最小數(這個數必然存在),0、2都不行,5可以,將5和2交換得到"956220",然後再將替換點後的字串"6220"顛倒即得到"950226"。

對於像"4321"這種已經是最「大」的排列,採用stl中的處理方法,將字串整個顛倒得到最「小」的排列"1234"並返回false。

//

全排列的非遞迴實現

#include using

namespace

std;

void swap(char *a, char *b)

//反轉區間

void reverse(char *a, char *b)

//下乙個排列

bool next_permutation(char

a) }

reverse(p, pend);

//如果沒有下乙個排列,全部反轉後返回true

1.全排列就是從第乙個數字起每個數分別與它後面的數字交換。

2.去重的全排列就是從第乙個數字起每個數分別與它後面非重複出現的數字交換。

3.全排列的非遞迴就是由後向前找替換數和替換點,然後由後向前找第乙個比替換數大的數與替換數交換,最後顛倒替換點後的所有資料。

參考文獻:

全排列遞迴演算法

全排列是將一組數按一定順序進行排列,如果這組數有n個,那麼全排列數為n 個。現以為 例說明如何編寫全排列的遞迴演算法。1 首先看最後兩個數4,5。它們的全排列為4 5和5 4,即以4開頭的5的全排列和以5開頭的4的全排列。由於乙個數的全排列就是其本身,從而得到以上結果。2 再看後三個數3,4,5。它...

全排列(遞迴演算法)

一 全排列演算法 從n個不同元素中任取m m n 個元素,按照一定的順序排列起來,叫做從n個不同元素中取出m個元素的乙個排列。當m n時所有的排列情況叫全排列。公式 全排列數f n n 定義0 1 演算法 遞迴演算法 網路上偷了乙個圖 全排列 順便複習乙個數學公式 排列的定義 從n個不同元素中,任取...

全排列遞迴演算法

對於乙個長為 n 的陣列,它的全排列一共有 n!種可能,演算法複雜度最小為o n!如果還需要列印出結果,那麼演算法複雜度為 o n n!演算法設計的思路是,對於第一位給定乙個值,剩下的 n 1 位進行全排列,然後通過乙個迴圈遍歷第一位所有可能的值,這裡我們是通過交換來改變第一位的值,對於 n 1 位...