为你写诗

c/c++
随笔 - 32, 文章 - 0, 评论 - 3, 引用 - 0
数据加载中……

生成下一个排列的字典序法

生成下一个排列的字典序法

字典序法中,对于数字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<pi+1}
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pj,pk
4)再将pj+1......pk-1pjpk+1pn反转,这就是排列p的下一个下一个排列。

例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下: 
自右至左找出排列中第一个比右边数字小的数字4          839647521
在该数字后的数字中找出比4大的数中最小的一个5        839647521
将5与4交换                                                                         839657421
将7421倒转                                                                          839651247
所以839647521的下一个排列是839651247。
程序代码如下:
Private Sub Dict(p() As Integer, ByVal 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                '找出递减子序列
Next
Swap p(i), p(j)                   '将递减子序列前的数字与序列中比它大的第一个数交换
For j = n To 1 Step -1                            '将这部分排列倒转
i = i + 1
If i >= j Then Exit For
Swap p(i), p(j)
Next
OutL p                                                     '输出一个排列
i = n
   End If
   i = i - 1
Loop
End Sub
Swap p(i), p(j)是交换两个元素的子过程,OutL p是输出排列的子过程。

posted on 2011-07-18 17:19 pp_zhang 阅读(1076) 评论(0)  编辑 收藏 引用 所属分类: Ialgo


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理