2011-01-06 8 views
2

Ich bin neu auf Prolog und meine Fähigkeiten zu verbessern ich versuche, etwas Bewegung zu machen. Im Moment arbeite ich mit einem BFS bin stecken, lassen vermuten, der Baum so etwas wie dieses:Prolog bekommen Elemente in verschiedenen Listen mit BFS

[tree(tree(tree(nil,b,nil),a,tree(tree(nil,d,nil),c,tree(nil,e,nil)))] 

nach meiner Anfrage habe ich so etwas wie

X=a; 

X=b; 

X=c; 

X=d; 

X=e; 

oder zumindest:

X=a,b,c,d,e; 

ich frage mich, wie durch Tiefenebenen als Ausgang, so etwas wie geordnete Ergebnisse haben:

X=[a]; 

X=[b,c]; 

X=[d,e]; 

oder, im besten Fall, so etwas wie:

X=[ [a] , [b,c] , [d,e] ]; 

Hilfe!

+0

Danke an Tim Cooper für den richtigen Beitrag, ich bin ziemlich noob ^^ " – RobCos

Antwort

0

Bessere Lösung, diesmal O (n). Es ist immer noch ein bisschen hässlich, weil ich die tatsächliche BFS von der Lösungsverarbeitung getrennt habe, aber das sollte es tun.

bfs2(Tree, Result) :- 
    bfs_queue([[Tree, 0]], Queue), 
    queue_to_result(Queue, Result). 
bfs_queue([], []) :- !. 
bfs_queue([[[],_]|Rest], RestResult) :- 
    !, bfs_queue(Rest, RestResult). 
bfs_queue([[[Element, Left, Right], Level]|Rest], [[Element,Level]|RestResult]) :- 
    NextLevel is Level + 1, 
    append(Rest, [[Left, NextLevel], [Right, NextLevel]], NewQueue), !, 
    bfs_queue(NewQueue, RestResult). 

process_level([[Item, Level]|Rest], Level, [Item|RestResult], OutOfLevel) :- 
    !, process_level(Rest, Level, RestResult, OutOfLevel). 
process_level(OutOfLevel, _, [], OutOfLevel) :- !. 
queue_to_result(Queue, Result) :- 
    !, queue_to_result(Queue, 0, Result). 
queue_to_result([], _, []) :- !. 
queue_to_result(Queue, Level, [Current|Result]) :- 
    !, process_level(Queue, Level, Current, NewQueue), 
    NewLevel is Level + 1, 
    queue_to_result(NewQueue, NewLevel, Result). 

Wieder stellte ich Bäume als drei Elementlisten dar.

+0

danke !! Es funktioniert !! Ich studiere von" Learn Prolog Now ", aber ich denke, es ist ein bisschen zu einfach. Was ist anderes Buch zum Lernen von? – RobCos

+0

Diese Version führt wesentlich schlechter als bfs/2. Ich testete es mit: n_tree (0, []): -! n_tree (N0, [N0, Links, Rechts]): - N1 ist N0 - 1, n_tree (N1, links), n_tree (N1, Right) und die Abfrage:? - zwischen (0, 20, N), n_Tree (N, T), Zeit (bfs (T, Nodes)), false mit beiden Versionen – mat

+0

Die Konstante ist viel höher mit dieser, weil sie die Zwischenliste der Listen erzeugt, außerdem wird die bfs/2 viel schlechter, wenn der Baum größer wird, in der Verarbeitungsebene n müssen Ebenen durchlaufen werden 0 bis n - 1, und es speichert keine Zwischenprodukte, daher ist das O (n^2) –

1

Ich habe eine Lösung, aber es ist nicht besonders effizient. Ich habe den Baum als eine Reihe von drei Elementlisten implementiert, wie [Element, Links, Rechts], aber es sollte genauso funktionieren.

% returns a list of nodes at the given level of the tree 
level([], _, []). 
level([Element, _, _], 0, [Element]) :- !. 
level([_, Left, Right], N, Result) :- 
    NewN is N - 1, 
    level(Left, NewN, LeftResult), 
    level(Right, NewN, RightResult), 
    append(LeftResult, RightResult, Result). 

% does a bfs, returning a list of lists, where each inner list 
% is the nodes at a given level 
bfs(Tree, Result) :- 
    level(Tree, 0, FirstLevel), !, 
    bfs(Tree, 1, FirstLevel, [], BFSReverse), 
    reverse(BFSReverse, Result). 
bfs(_, _, [], Accum, Accum) :- !. 
bfs(Tree, Num, LastLevel, Accum, Result) :- 
    level(Tree, Num, CurrentLevel), !, 
    NewNum is Num + 1, 
    bfs(Tree, NewNum, CurrentLevel, [LastLevel|Accum], Result). 

Es sollte möglich sein, dies in O (n) zu tun, aber das ist O (n^2). Ich begann, an einer anderen Lösung zu arbeiten, die die Ebene jedes Elements in O (n) zurückgibt, aber ich bin mir nicht sicher, wie ich diese Liste in das Lösungsformat in O (n) umwandeln kann, ohne auf Assert/Retract zurückgreifen zu müssen.