枚举全部:从最小一路走到最大
有了「下一个排列」这一步,枚举全体几乎不费力气:从升序(字典序最小)出发,反复调用 next,每次跳到紧邻的下一个,直到抵达降序(字典序最大)。整条路径恰好不重不漏地覆盖全部 n! 个排列——因为「下一个」是严格递增且无遗漏的。
本页单步观察清单按字典序逐行点亮;留意每一步用到的支点位置,它解释了相邻两个排列差在哪几位。
为什么不重不漏?
字典序是所有排列上的一个全序(任意两个都能比大小、不会相等)。「下一个排列」给出的是严格大于当前、且没有任何排列夹在中间的那一个。于是从最小反复取下一个,就像沿数轴一格格走,既不会跳过谁,也不会回头重复,走到最大(取不到下一个)时正好遍历完 n! 个。
它就是标准库的 permutations。 Python 的 itertools.permutations(range(1,n+1)) 与 C++ 里「sort 后反复 next_permutation 直到返回 false」产出的正是这条字典序序列。需要按序处理全部排列(枚举所有座位 / 赛程 / 路径次序)时,这套「最小 → 反复 next →
最大」是最省心的写法。
n!增长极快。 10! = 3,628,800, 13! 已超 60 亿。逐个枚举只适合很小的 n;当 n 稍大、又只需要「第 k 个」或「某排列的编号」时,不要从头走——用康托展开在
内直接换算。生成视角的另一面是回溯: 同一批排列,换成递归树来铺。