我对比较不同技术/方法来生成给定集合的所有可能排列很感兴趣。
我对比较不同技术/方法来生成给定集合的所有可能排列很感兴趣。
void permute(Element[] permutationPrefix, Set rest)
{
if (rest.IsEmpty) {
// permutationPrefix is now a full permutation
print(permutationPrefix);
} else {
foreach (element in rest) {
permutationPrefix.Append(element);
permute(permutationPrefix, rest.Minus(element))
permutationPrefix.Length--; // cut away the last item
}
}
}
最初使用空的permutationPrefix
和rest
保存完整集合进行调用;如果该集合是一个排序数据结构,则排列将按字典顺序输出。
请注意,我们在每个递归调用中都会复制并修改集合,这是整个算法中最昂贵的操作,可能与print
方法一起。单个集合复制的成本与排列总数n
的对数成比例;由于递归调用堆栈的深度也是对数级别的,因此得出O(n.log(n).log(n))的性能估计。
(这个算法也适合转换成一个表现良好的随机排列生成器。)
这个问题已经被问过并得到了答案(事实上多次问过):
我个人认为Steinhaus算法在思考问题时有些过度:它的速度并不比最原始的实现快多少。
以下是最基本实现的类似Java的伪代码:
List<List<Element>> generateAllPermutations(List<Element> input)
{
List<Element> output = new ArrayList<Element>();
if (input.size() == 0)
return output;
for (Element first : input) {
for (List<Element> sequence : generateAllPermutations(input - first))
output.add(first + sequence);
}
}