再議“生成全排列算法”
看了“白話算法(7) 生成全排列的幾種思路(一)”和“白話算法(7) 生成全排列的幾種思路(二) 康托展開”。在此,將以前本人推導的全排列算法介紹一下,和廣大的網友交流一下。
以例子說明,用0、1、2、3,四個數組成全排列。
首先可以知道,這四個數組成的全排列一共有4!=24個。那么給這24個全排列編號,分別為0、1、2……23。再給定一個算法,通過編號計算出一個全排列。本文的目的就是找到這樣的算法。
把所有的全排列列舉出來可以發現,0在末位的有6個,1在末位的有6個,等等。
觀察0在末位的六個,分別是
1、2、3、0
1、3、2、0
2、1、3、0
2、3、1、0
3、1、2、0
3、2、1、0
可以看出這6個全排列,除了末位是0外,前面三個數正好是1、2、3的全排列
再觀察1在末位的六個,分別是
0、2、3、1
0、3、2、1
2、0、3、1
2、3、0、1
3、0、2、1
3、2、0、1
也可以看出這6個全排列,除了末位是1外,前面三個數正好是0、2、3的全排列
類似的,末位是2和3的6個全排列,除了末位是一樣的以外,前面三個數正好是剩下的三個數的全排列。
于是該問題就可以用下面的步驟來解決。
1、根據編號確定末位數字
2、確定末位數字后,獲得剩余的數字
3、對編號適當的處理,得到新的編號
4、問題演化成除了末位數字后,用新的編號和剩余的數字,計算剩余數字的全排列。
再用一個具體的例子來說明。比方說,用編號13來計算0、1、2、3的一個全排列。
1、先給這4個數字排好序。是0、1、2、3
2、計算[13/3!]+1=3,表示末位數是第3個數。注:[X]表示取X的整數部分。
3、把第3個數和第4個數(未排的最后1個數)交換。此時,數字的順序是0、1、3、2。藍色的表示已經排好。
4、新的編號為13 mod 3!=1
5、計算[1/2!]+1=1,表示末位數是第1個數。
6、把第1個數和第3個數(未排的最后1個數)交換。此時,數字的順序是3、1、0、2。藍色的表示已經排好。
7、新的編號為1 mod 2!=1
8、計算[1/1!]+1=2,表示末位數是第2個數。
9、把第2個數和第2個數(未排的最后1個數)交換。此時,數字的順序是3、1、0、2。藍色的表示已經排好。
10、因為只剩下一個數,所以編號13對應的全排列就是3、1、0、2
其他的編號計算方法和此一樣。
后面的這個表格就是按照上面的算法得到所有的編號和全排列的關系
| A(0) | A(1) | A(2) | A(3) | 編號 |
| 1 | 2 | 3 | 0 | 0 |
| 2 | 1 | 3 | 0 | 1 |
| 2 | 3 | 1 | 0 | 2 |
| 3 | 2 | 1 | 0 | 3 |
| 1 | 3 | 2 | 0 | 4 |
| 3 | 1 | 2 | 0 | 5 |
| 3 | 2 | 0 | 1 | 6 |
| 2 | 3 | 0 | 1 | 7 |
| 2 | 0 | 3 | 1 | 8 |
| 0 | 2 | 3 | 1 | 9 |
| 3 | 0 | 2 | 1 | 10 |
| 0 | 3 | 2 | 1 | 11 |
| 1 | 3 | 0 | 2 | 12 |
| 3 | 1 | 0 | 2 | 13 |
| 3 | 0 | 1 | 2 | 14 |
| 0 | 3 | 1 | 2 | 15 |
| 1 | 0 | 3 | 2 | 16 |
| 0 | 1 | 3 | 2 | 17 |
| 1 | 2 | 0 | 3 | 18 |
| 2 | 1 | 0 | 3 | 19 |
| 2 | 0 | 1 | 3 | 20 |
| 0 | 2 | 1 | 3 | 21 |
| 1 | 0 | 2 | 3 | 22 |
| 0 | 1 | 2 | 3 | 23 |
通過這樣的算法,通過指定的編號就能算出一個全排列。
如果要遍歷所有的全排列,則只要遍歷編號就能完成。
如果要隨機獲得一個全排列,則隨機生成一個編號,再計算出全排列就可以了。
具體的代碼在我之前的文章“遍歷排列的實現——VB2005”中,這里就不重復貼出了。

浙公網安備 33010602011771號