您的位置:首页 > 其它

关于Johnson-Trotter和字典序排列在《算法设计与分析基础》中的论述

2016-03-09 12:08 239 查看
这是我在看书时看到的,开始看的时候觉得不理解,后来看了两遍觉得豁然开朗,分享给大家。加了点我自己的理解,希望大家觉得有帮助。

对于n的较小值来说,不用生成排列的方式来得到n个元素的相同次序的排列是有可能的。为了做到这一点,我们给一个排列中的每个元素k赋予一个方向。我们在所讨论的每个元素上画一个小箭头来指出它的方向,例如:→←→←

3 2 4 1

如果元素k的箭头指向一个相邻的较小元素,我们说它在这个以箭头标记的排列中是移动(mobile)的。例如,对于上面的排列来说,3和4是移动的,因为3指向2、4指向1,而2和1不是移动的。通过使用移动元素这个概念,我们可以给出所谓的Johnson-Trotter算法的描述,它也是用来生成排列的。

算法 Johnson-Trotter(n)

//实现用来生成排列的Johnson-Trotter算法

//输入:一个正整数n

//输出:{1,...,n}的所有排列的列表

←← ←

将第一个排列初始化为 1 2 ... n

while 存在一个移动元素 do

求最大的移动元素k

把k和它箭头指向的相邻元素互换

调转所有大于k的元素的方向

将新排列添加到列表中

对于n=3应用该算法,其中最大的移动整数用粗体字表示:

←←← ←←← ←←← →←← ←→← ←←→

1 2 3 1 3 2 3 12 3
2 1 2 3 1 2 1 3

这个算法是生成排列的最有效的算法之一。该算法实现的运行时间和排列的数量是呈正比的。当然,除非n的值非常小,否则它的速度是慢的难以忍受的。然而,这不是这个算法的错,而应该说是这个问题的“错”:它要求生成的项的确是太多了。

有人可能会说Johnson-Trotter算法生成的排列的次序不是非常自然。例如,排列n n-1 ... 1的自然位置似乎应该是列表的最后一个。将排列按照升序队列,的确是这样的,这也被称为字典序,如果数字被解释成字母表中的字符,这就是它们在字典中的排列顺序。例如,对于n=3来说,

123 132 213 231 312 321

如何按照字典序生成a1a2...an-1an后面的排列呢?如果an-1<an(肯定有一半序列是这样的情况),可以简单地调换最后这两个元素的位置。例如,123后面应该是132.如果an-1>an,则需要找到序列的最长递减后缀ai+1>ai+2>...>an(但ai<ai+1);然后把ai与后缀中大于它的最小元素进行交换,以使ai增大;再将新后缀颠倒,使其变为递增排列。例如,362541中5>4>1而2<5,故将5、4、1中大于2的最小后缀4与其交换得到364521,而后再将新后缀颠倒得到364125为362541以字典序生成排列的下一个排列。下面就是这个简单算法的伪代码,其思想可以远溯到14世纪的印度。

算法 LexicographicPermute(n)

//以字典序产生排列

//输入:一个正整数n

//输出:在字典序下{1,...,n}所有排列的列表

初始化第一个排列为 1 2 ... n

while 最后一个排列有两个连续升序的元素 do

找出使得ai<ai+1的最大的i //ai+1>ai+2>...>an

找到使得ai<aj的最大索引j //j>=i+1,因为ai<ai+1

交换ai和aj //a1a2...an仍保持降序

将ai+1到an的元素反序

将这个新排列添加到列表中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: