全排列生成算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
全排列的生成算法对于给左的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。字典序法按照字典序求下一个排列的算法广例字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:123,132,213,231,312,321o注意一个全排列可看做一个字符串,字符串可有前缀、后缀/生成给泄全排列的下一个排列所谓一个全排列的下一个排列就是这一个排列与下一个排列之间没有其他的排列。这就要求这一个排列与下一个排列有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。广例839647521是1—9的排列。1—9的排列最前而的是123456789,最后而的是987654321,从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。算法:由P1P2...Pn生成的下一个排列的算法如下:1求j=max{j| Pj-I 全排列的生成算法 2008年04月25日星期五下午03:23 全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出來。任何n个字符集的排列都可以与1〜n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。 n个字符的全体排列之间存在一个确定的线性顺序关系。所有的排列中除最后一个排列外,都有一个后继:除第一个排列外,都有一个前驱。每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。 全排列的生成法通常有以下几种: 字典序法 递増进位数制法 递减进位数制法 邻位交换法 n进位制法 递归类算法 1 •字典序法 字典序法中,对于数字仁2、3……n的排列.不同排列的先后关系是从左到右逐个比较对应的数字的先后來决定的。例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。按照这样的规定, 5个数字的所有的排列中最前面的是12345,最后面的是54321 o 字典序算法如下: 设P是1~n的一个全排列:p=p1p2……pn=plp2……pj-lpjpj+1……pk-1pkpk+1……pn 1) 从排列的右端开始,找出第一个比右边数字小的数字的序号j (j从左端开始il•算),即j=max{i|pi 2) 在pj的右边的数字中,找出所有比pj大的数中报小的数字pk.即k=max{i|pi>pj}(右边的数从右至左是递増的•因此k是所有大干pj的数字中序号最大者) 3) 对换pi. pk 4) 再将pj+1……pk-lpkpk+lpn倒转得到排列p=plp2••…pj-lpjpn••…pk+1pkpk-1••…pj+1,这就是排列p的下一个下一个排列。 例如839647521是数字1〜9的一个排列。从它生成下一个排列的步骤如下: 自右至左找出排列中第一个比右边数字小的数字4 839647521 在该数字后的数字中找出比4大的数中最小的一个5 839647521 将5与4交换839657421 将7421 倒转839651247 所以839647521的下一个排列是839651247。 程序代码如下: Private Sub Dict(p() As Integer, ByVai n As Integer) Dim i As Integer, j As Integer OutL p i = n -1 Do While i > 0 If p(i) < p(i + 1) Then For j = n To i + 1 Step -1 •从排列右端开始 If p(i) <= p(j) Then Exit For ■找出递减子序列 i = i + 1 Next Swap p(i)t p(j) ■将递减子序列前的数字与序列中比它大的第一个数交换For j = n To 1 Step -1•将这部分排列倒转 If i >= j Then Exit For Swap p(i), p(j) Next OutLp '输出一个排列 1 = n End If i = i -1 Loop End Sub Swap p(i)t p(j)是交换两个元素的子过程.OWL p是输出排列的子过程。 2 •递增进位数制法 在递增进位制数法中.从一个排列求另一个排列需雯用到中介数。如果用ki表示排列plp2...pi...pn中元素pi的右边比pi 小的数的个数.则排列的中介数就是对应的排列ki……ki……kn-l o 例如排列839647521的中介数是72642321, 7、2、6 .................分别是排列中数字& 3、9 ................ 的右边比它小的数字个数。 中介数是计算排列的中间环节。已知一个排列,要求下一个排列,首先确定其中介数.一个排列的后继.其中介数是原排列中介数加仁需要注意的是,如果中介数的末位kn-1+1=2.则要向前进位,一般情形,如果ki+1=n-i+1,则要进位,这就是所谓的递增进位制。例如排列839647521的中介数是72642321,则下一个排列的中介数是 67342221+1=67342300(W为1+1=2,所以向前进位.2+1=3,又发生进位,所以下一个中介数是67342300)。 得到中介数后,可根据它还原对应得排列。算法如下: 中介数k1、k2 ............ kn-1的各位数字顺序表示排列中的数字n、.............. 2在排列中距右端的的空位数• 因此,要按k仁k2 ................ kn-1的值从右向左确定n. n-1 .................. 2的位宜•并逐个放置在排列中:i放在 右起的ki+1位,如果某位已放有数字,则该位宜不算在内,最后一个空位放仁 因此从67342300可得到排列849617523,它就是839647521的后一个排列。因为9最先放宜,k1=6, 9 放在右起第7位.空出6个空位.然后是放8, k2=7, 8放在右起第8位,但9占用一位,故8应放在右起第9位.余类推。 程序代码如下: Private Sub lncr(p() As Integer, ByVai n As Integer) Dim m() As Integer '保存中介数的数组 Dim i As Integer, j As Integer Dim a As Integer ReDim m(n) For i = 1 To n'第一个排列的中介数为000 0 i = i + 1