这是一个用 Smalltalk 编写的算法。
该算法的思想是考虑长度为 m 且元素介于 1 和 n 之间的数组的字典顺序。给定任何这样的array,方法next 用它按所述顺序的下一个部分排列替换array。
我创建了一个包含三个实例变量的类
array the current permutation of length m
m the size of array
complement the SortedCollection of integers not in array
实例创建方法m:n:工作原理如下
m: length n: limit
m := length.
array := (1 to: m) asArray.
complement := (m + 1 to: limit) asSortedCollection
在这个类中,next 方法修改了array,以便它现在可以保存下一个排列。
值得一提的是该算法不是递归的。
next 方法以 nil 回答,但 array 包含顺序中的最后一个排列(即 array = (n, n-1, ...., n-m+1)。
要计算所有排列,从array = (1 ... m) 开始并发送next,直到答案为nil。
next
| index max h a c |
index := self lastDecreasingIndex.
max := complement max.
h := (index to: m) findLast: [:i | (array at: i) < max] ifAbsent: nil.
h isNil
ifTrue: [
index = 1 ifTrue: [^nil].
a := array at: index - 1.
index to: m do: [:i | complement add: (array at: i)].
c := complement detect: [:cj | a < cj].
array at: index - 1 put: c.
complement remove: c; add: a.
index to: m do: [:i | array at: i put: complement removeFirst]]
ifFalse: [
h := h + index - 1.
a := array at: h.
c := complement detect: [:ci | a < ci].
array at: h put: c.
complement remove: c; add: a.
h + 1 to: m do: [:i | complement add: (array at: i)].
h + 1 to: m do: [:i | array at: i put: complement removeFirst]]
在哪里
lastDecreasingIndex
| index |
index := m.
[(array at: index - 1) > (array at: index)] whileTrue: [
index := index - 1.
index = 1 ifTrue: [^1]].
^index