全排列的四种生成算法

1.字典序法

 

字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。例如对于5个数字的排列 12354和12345,排列12345在前,排列12354在后。按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是 54321。

字典序算法如下:


设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn


1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即  j=max{i|pi
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pi,pk
 4)再将pj+1......pk-1pkpk+1pn倒转得到排列p''=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。


例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
 自右至左找出排列中第一个比右边数字小的数字4            839647521
在该数字后的数字中找出比4大的数中最小的一个5        839647521
将5与4交换     839657421
将7421倒转    839651247
所以839647521的下一个排列是839651247。


2.递增进位数制法


在递增进位制数法中,从一个排列求另一个排列需要用到中介数。如果用 ki表示排列p1p2...pi...pn中元素pi的右边比pi小的数的个数,则排列的中介数就是对应的排列k1 ...... ki...... kn-1。
例如排列839647521的中介数是72642321,7、2、6、......分别是排列中数字8、3、9、......的右边比它小的数字个数。


中介数是计算排列的中间环节。已知一个排列,要求下一个排列,首先确定其中介数,一个排列的后继,其中介数是原排列中介数加1,需要注意的 是,如果中介数的末位kn-1+1=2,则要向前进位,一般情形,如果ki+1=n-i+1,则要进位,这就是所谓的递增进位制。例如排列 839647521的中介数是72642321,则下一个排列的中介数是67342221+1=67342300(因为1+1=2,所以向前进 位,2+1=3,又发生进位,所以下一个中介数是67342300)。
得到中介数后,可根据它还原对应得排列。

 

算法如下:


中介数k1、k2、......、kn-1的各位数字顺序表示排列中的数字n、n-1、......、2在排列中距右端的的空位数,因此, 要按k1、k2、......、kn-1的值从右向左确定n、n-1、......、2的位置,并逐个放置在排列中:i放在右起的ki+1位,如果某位已 放有数字,则该位置不算在内,最后一个空位放1。
因此从67342300可得到排列849617523,它就是839647521的后一个排列。因为9最先放置,k1=6,9放在右起第7位,空出6个空位,然后是放8,k2=7,8放在右起第8位,但9占用一位,故8应放在右起第9位,余类推。

 

3.递减进位制数法


在递增进位制数法中,中介数的最低位是逢2进1,进位频繁,这是一个缺点。把递增进位制数翻转,就得到递减进位制数。
 839647521 的中介数是67342221(k1k2...kn-1),倒转成为12224376(kn-1...k2k1),这是递减进位制数的中介 数:ki(i=n-1,n-2,...,2)位逢i向ki-1位进1。给定排列p,p的下一个排列的中介数定义为p的中介数加1。例如 p=839647521,p的中介数为12224376,p的下一个排列的中介数为12224376+1=12224377,由此得到p的下一个排列为 893647521。

给定中介数,可用与递增进位制数法类似的方法还原出排列。但在递减进位制数中,可以不先计算中介数就直接从一个排列求出下一个排列。具体算法如下:

1)如果p(i)=n且i<>1,则p(i)与p(i-1)交换
2)如果p(1)=n,则找出一个连续递减序列9、8、......、i,将其从排列左端删除,再以相反顺序加在排列右端,然后将i-1与左边的数字交换
例 如p=893647521的下一个排列是983647521。求983647521的下一个排列时,因为9在最左边且第2位为8,第3位不是7,所以将8 和9从小到大排于最右端364752189,再将7与其左方数字对调得到983647521的下一个排列是367452189。又例如求 987635421的下一个排列,只需要将9876从小到大排到最右端并将5与其左方数字3对调,得到534216789。

4、邻位对换法

      1)如果一个元素的移动方向所指向的那个邻位比它小,此元素就是可移的;相反,如果一个元素的移动方向所指向的那个邻位比它大,此元素就是不可移的。如果一个元素的移动方向上没有邻位,此元素也是不可移的。
  2)每次都是先寻找最大的可移元素 max,把它与移动方向所指向的那个邻位交换,然后把所有比 max 大的元素的移动方向反转。
  3)不断重复(2),直到所有元素都不可移为止。

       以 1234数列为例。

       初始使,所有元素移动方向向左。

        故4为2)步骤选出的max,移动;变为1243

        重复2)步骤直到选不出可移动元素停止。

        即可得出1234的12种全排列。




你可能感兴趣的:(数学与算法)