修改堆生成排列的算法

时间:2014-04-24 18:57:41

标签: algorithm permutation

Heap's algorithm是一种循环的系统方式 N个元素的所有排列“一次一个交换”。对于奇数N, 它特别整洁,因为最终的排列似乎只是 与第一次排列不同的一次交换。

但是,即使是N,这种环绕也不会发生。例如,对于 N = 4,排列顺序为:

1234
2134
3124
1324
2314
3214
4213
2413
1423
4123
2143
1243
1342
3142
4132
1432
3412
4312
4321
3421
2431
4231
3241
2341

那么,是否有人有一个交换算法,甚至包含N? 如果没有,那么N = 4怎么样?

2 个答案:

答案 0 :(得分:2)

通过检查,满足约束的一个可能的序列是:

1234
1432
3412
4312
1342
3142
4132
4231
2431
3421
4321
2341
3241
1243
2143
4123
1423
2413
4213
3214
2314
1324
3124
2134
1234

每一步都应该只交换两个元素。

对于较大的N,我建议您尝试实现Steinhaus–Johnson–Trotter algorithm,我相信只使用相邻元素的交换生成这些排列,并且会让您与初始位置进行一次交换。

基于rosetta code的Python代码:

N=4
def s_permutations(seq):
    def s_perm(seq):
        if not seq:
            return [[]]
        else:
            new_items = []
            for i, item in enumerate(s_perm(seq[:-1])):
                if i % 2:
                    new_items += [item[:i] + seq[-1:] + item[i:]
                                  for i in range(len(item) + 1)]
                else:
                    new_items += [item[:i] + seq[-1:] + item[i:]
                                  for i in range(len(item), -1, -1)]
            return new_items

    return [(tuple(item), -1 if i % 2 else 1)
            for i, item in enumerate(s_perm(seq))]

for x,sgn in s_permutations(range(1,N+1)):
    print ''.join(map(str,x))

答案 1 :(得分:0)

对于固定的小数,例如N = 4,您可以预先计算数组索引的所有排列,并使用索引的每个排列来运行数据,以得到数据的所有排列,例如,在伪代码中

originalData[] = { 1111, 2222, 3333, 4444 }
indexPermuations[0] = { 0, 1, 2, 3 }
indexPermuations[1] = { 0, 1, 3, 2 }
// Etc for all 16 permutations of 4 indices

foreach (ip in indexPermutations) 
{
    for (i = 0 to 3)
    {
        dataPermuation[ip][i] = originalData[indexPermutation[ip][i]];
    }
}