За пример, нека приемем следното представяне на дърво:
- Атомът
nil
представлява празното дърво.
- Структурата
tree/3
представлява непразно дърво tree( Left , Right , Payload )
, където Left
и Right
представляват (съответно и рекурсивно) лявото и дясното поддървета, а Payload
е полезният товар за възела: във вашия случай списък.
Много/повечето рекурсивни проблеми имат 1 или 2 „специални случая“ и по-общия случай. Това не е по-различно:
Специалният случай е този на празното дърво: изравняването му създава празния списък.
Общият случай е този на непразно дърво: изравняването му се състои от следните стъпки:
Кодът на Prolog за постигане на това е почти идентичен с описанието на английски по-горе:
flatten_tree( nil , [] ) . % flattening the empty tree yields an empty list, n'est-ce-pas?
flatten_tree( tree(Left,Right,Payload) , Result ) :- % flattening a non-empty tree consists of
flatten_tree( Left , Prefix ) , % - flattening the left subtree,
flatten_tree( Right , Suffix ) , % - flattening the right subtree,
concatenate( Prefix , Payload , Suffix , Result ) % - concatenating the three parts
. % - easy!
concat( Xs, Ys , Zs , Rs ) :-
append(Xs,Ys,T1) ,
append(T1,Zs,Rs)
.
Може да се отбележи, че друг подход може да бъде използването на findall/3
и append/2
(ако използвате SWI пролог).
Първо се нуждаете от предикат, за да посетите дървото чрез обратно проследяване:
visit( tree(L,_,_) , P ) :- visit( L , P ) . % visit the left subtree
visit( tree(_,_,P) , P ) . % visit the current node
visit( tree(_,R,_) , P ) :- visit( R , P ) . % visit the right subtree
Чувствайте се свободни да пренаредите реда на клаузите, за да получите реда, който искате. След като имате това, изравняването на дървото е тривиално:
flatten_tree( Tree , List ) :-
findall( X, visit(Tree,X) , Xs ) ,
append(Xs,List)
.
person
Nicholas Carey
schedule
07.05.2015