相當棘手的一個序言,但這裏有一個解決方案來考慮它提供了一個真正的level-order (L-R breadth-first)樹遍歷:
nivel(nodo(L,Root,R), Level) :-
depth_value_pairs(nodo(L,Root,R), 0, DVPairs),
keylistmerge(DVPairs, Groups),
maplist(keyvalue, Groups, _, Values),
member(Level, Values).
nivel/2
是您的輸入謂詞。基本上,其使用depth_value_pairs/3
,其產生Depth-Value
形式的解(例如,0-t
以表示層深度的根節點t
或1-4
以表示在層深度1
等處的節點4
)。然後,它使用keylistmerge/2
將所有深度值對列表合併成深度組,例如[0-[t], 1-[4,t], ...]
。然後,maplist(keyvalue...
調用從列表中刪除Depth-
部分,並且最終謂詞調用member/2
選擇每個列表以綁定到輸出Level
。
下面是其他謂詞的定義:
depth_value_pairs(vacio, _, []).
depth_value_pairs(nodo(L, Root, R), Depth, [Depth-Root|Level]) :-
NextLevel is Depth + 1,
depth_value_pairs(L, NextLevel, LL),
depth_value_pairs(R, NextLevel, RL),
append(LL, RL, Level).
keyvalue(K-V, K, V).
keylistmerge(KVL, MKVL) :-
keysort(KVL, [K-V|KVs]),
keylistmerge([K-V|KVs], K, [], MKVL).
keylistmerge([], K, Acc, [K-Acc]).
keylistmerge([K0-V|KVs], K, Acc, MKVL) :-
K == K0, !,
append(Acc, [V], NewAcc),
keylistmerge(KVs, K, NewAcc, MKVL).
keylistmerge([K0-V|KVs], K, Acc, [K-Acc|MKVs]) :-
keylistmerge(KVs, K0, [V], MKVs).
行使這給了我們:
?- nivel(nodo(nodo(vacio,4,nodo(vacio,5,vacio)), t, nodo(vacio,r,vacio)), Level).
Level = [t] ;
Level = [4, r] ;
Level = [5] ;
false.
請注意,我們依靠內置keysort/2
是保序(穩定)以保留二叉樹中節點的LR順序。