我的评论旨在作为直接生成单循环排列的提示,而不是生成所有排列并过滤掉由单循环组成的排列。
我们或许应该澄清一下,经常使用两种排列表示。 xyz 写道“我知道如何 [to] 生成所有排列 [s]”,大概意思类似于我在 this 2006 forum post 中给出的代码。这里所有排列都是根据列表重新排列某些“标准顺序”列表中的项目的方式表示的。
显然有N个!各种排列。其中有多少是单周期排列?这个问题很容易通过考虑对排列有用的另一种形式来回答,即作为不相交循环的产物。我们需要区分像 (1,2,3,4) 这样的循环和恒等排列 [1,2,3,4]。实际上,循环 (1,2,3,4) 将 1 映射到 2, 2 映射到 3, 3 映射到 4, 以及 4 映射回 1,所以它不是恒等排列,而是 [2,3,4,1]它的列表表示。
现在一个循环在自身上循环,所以我们选择从哪里开始循环表示法是任意的。例如,如果我们从 1 开始,则循环由以下 N-1 项的排序决定。这表明有 (N-1) 个!形成单个循环(长度必然为 N)的 N 个事物的排列。因此,我们可以很容易地以循环形式生成所有单循环排列,然后问题就归结为从该循环形式转换为排列的列表形式。 [请注意,Mog 部分处理了另一个方向的转换:给定一个排列作为列表,找出该排列中包含的一个循环(并查看它是否是全长的)。]
这是我的代码,用于生成给定“标准顺序”列表的所有单循环列表排列,oneCycle(Identity,Permuted):
oneCycle([H|T],P) :-
permute(T,S),
oneCycle2permute([H|S],[H|T],P).
permute([ ],[ ]) :- !.
permute(L,[H|T]) :-
omit(H,L,Z),
permute(Z,T).
omit(H,[H|T],T).
omit(X,[H|T],[H|Z]) :-
omit(X,T,Z).
oneCycle2permute(_,[ ],[ ]) :- !.
oneCycle2permute(C,[I|Is],[P|Ps]) :-
mapCycle(C,I,P),
oneCycle2permute(C,Is,Ps).
mapCycle([X],X,X) :- !.
mapCycle([H|T],X,Y) :-
mapCycleAux(H,T,X,Y).
mapCycleAux(Y,[X],X,Y) :- !.
mapCycleAux(X,[Y|_],X,Y) :- !.
mapCycleAux(_,[X,Y|_],X,Y) :- !.
mapCycleAux(H,[_|T],X,Y) :-
mapCycleAux(H,T,X,Y).