8 Weitere Algorithmen

Werbung
Praktische Informatik I – Algorithmen und Datenstrukturen
8
Wintersemester 2006/07
Weitere Algorithmen
Algorithmenmuster (Design Patterns):
Scanline,
Rekursion, Divide–and–Conquer,
Graphendurchlauf: DFS, BFS,
Backtracking in Verbindung mit DFS,
Greedy,
Dynamische Programmierung.
Prof. Dr. Dietmar Seipel
416
Praktische Informatik I – Algorithmen und Datenstrukturen
8.1
Wintersemester 2006/07
Das Algorithmenmuster Greedy
greedy: engl. für gierig
Das Prinzip “gieriger” Algorithmen ist es, in jedem Teilschritt so viel wie
möglich zu erreichen.
Bei einigen Problemen wie der Berechnung kürzester Wege oder der
Suche nach einem aufspannenden Baum in einem Graphen kann man
mit einer geeigneten Greedy–Methode die Optimallösung finden.
Bei anderen Problemen wie etwa dem Rucksackproblem oder dem
Problem des Handlungsreisenden erreicht man damit aber meist nicht
die Optimallösung.
Prof. Dr. Dietmar Seipel
417
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Berechnung kürzester Wege auf Distanzgraphen –
Algorithmus von Dijkstra
Anwendung von Vorangswarteschlangen
, dessen Kanten
Gegeben sei ein gerichteter Graph
markiert sind (Distanzgraph).
nicht–negativen Längen
fixiert.
Desweiteren wird ein Knoten
mit
von zu
Prof. Dr. Dietmar Seipel
von kürzesten Wegen
Gesucht sind die Längen
allen anderen Knoten
.
418
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Beispiel:
Prof. Dr. Dietmar Seipel
419
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Dann gilt:
Prof. Dr. Dietmar Seipel
420
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Greedy–Algorithmus, Dijkstra
Setze
,
,
, für alle
.
Dann wird nach dem Prinzip „Knoten mit kürzester Distanz von zuerst“
erhält:
schrittweise vergrößert, bis man
.
mit minimaler Distanz
1. Wähle Knoten
zu
hinzu
ist bereits korrekt!)
durch:
, ersetze
zu
von
3. Füre jede Kante
2. Nimm
(
Prof. Dr. Dietmar Seipel
421
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
eines
Prof. Dr. Dietmar Seipel
Für alle Kanten aus kennt man bereits die Länge
kürzesten Weges von nach .
422
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Wir implementieren
als Vorrangswarteschlange (Priority Queue). Die
.
Prioritäten sind die Distanzen
Dann werden die 3 Schritte aus dem Algorithmus von Dijkstra
folgendermaßen realisiert:
1. Löschen des Minimums.
2. Einfügen.
3. Verringerung der Priorität eines Schlüssels.
Prof. Dr. Dietmar Seipel
423
Praktische Informatik I – Algorithmen und Datenstrukturen
8.2
Wintersemester 2006/07
Algorithmen zum Graphendurchlauf
Tiefensuche (Depth First Search, DFS)
Breitensuche (Breadth First Search, BFS)
Anwendung zur Suche in Labyrinthen
Prof. Dr. Dietmar Seipel
424
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
repräsentiert:
Das Labyrinth wird als Graph
Wir lassen der Einfachheit halber die inversen Kanten des Labyrinths weg.
Prof. Dr. Dietmar Seipel
425
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Rahmenalgorithmus zum Graphendurchlauf
,
,
Startknoten
Graph
und
Teilmengen
,
für Knotenmenge
Datenstruktur
Zielknotenmenge
.
Es werden kürzeste Wege von zu allen Knoten aus
Prof. Dr. Dietmar Seipel
berechnet.
426
Praktische Informatik I – Algorithmen und Datenstrukturen
;
ein;
in
füge
Wintersemester 2006/07
;
solange
noch Elemente enthält
wähle das erste Element
aus
falls es keine Kante
mit Knoten
dann lösche
aus
sonst { benutze eine Kante
,
d.h.
;
falls
dann {
;
füge
in
ein;
Vorgänger
;
falls
dann breche den Algorithmus ab } }
gibt
Prof. Dr. Dietmar Seipel
427
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Suche nach einem einzigen Zielknoten in JAVA
class GraphNode {
GraphNode[] neighbors;
boolean isVisited;
int key;
public GraphNode(int key) {
this.key = key;
}
public void setNeighbors(GraphNode... neighbors) {
this.neighbors = neighbors;
}
Prof. Dr. Dietmar Seipel
428
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
public List findPath(GraphNode destination) {
if (isVisited)
return null;
isVisited = true;
List path = null;
if (destination.key == this.key) {
path = new List();
path.add(key);
} else {
for (int i = 0; i < neighbors.length; i++) {
path = neighbors[i].findPath(destination);
if (path != null) {
path.insert(key, null);
break; } } }
return path;
}
Prof. Dr. Dietmar Seipel
429
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
public static void main(String[] args) {
GraphNode[] nodes = new GraphNode[5];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new GraphNode(i);
}
nodes[0].setNeighbors(nodes[1]);
nodes[1].setNeighbors(nodes[2], nodes[0]);
nodes[2].setNeighbors(nodes[3], nodes[4]);
nodes[3].setNeighbors(nodes[4]);
nodes[4].setNeighbors(nodes[1]);
System.out.println(nodes[4].findPath(nodes[0]));
}
}
Prof. Dr. Dietmar Seipel
430
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Tiefensuche:
Falls Border als Stapel realisiert wird, so ist das erste Element von Border
immer das oberste und wir fügen ein indem wir auf den Stapel legen.
Dann liefert der Rahmenalgorithmus eine Tiefensuche.
Beispiel:
Prof. Dr. Dietmar Seipel
431
Praktische Informatik I – Algorithmen und Datenstrukturen
.
und
Sei
Wintersemester 2006/07
Die Knoten werden in der Reihenfolge ihrer Nummern besucht.
benutzt.
wird zuerst die Kante
Für
Für
gibt es keine Kanten
nächsten unbenutzten Kante
für
. Deshalb fahren wir mit der
fort (Backtracking) .
Dann wird
analog zu
behandelt, und wir gelangen
schließlich über den Knotem 8 zum Ziel 9.
Die berechnete Vorgängerfunktion ist jetzt wie folgt:
1
3
4
5
6
7
8
9
1
2
3
4
4
6
6
8
Vorgänger
2
Der berechnete Weg vom Start zum Ziel ist also:
Prof. Dr. Dietmar Seipel
432
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Breitensuche:
Falls Border als Priority Queue (First In / First Out) realisiert wird, so
liefert der Rahmenalgorithmus eine Breitensuche
und
.
Sei weiter
Auch hier werden die Knoten wieder in der Reihenfolge ihrer Nummern
besucht und der berechnete Weg ist der derselbe. Aber jetzt werden für
zuerst die beiden Kanten
und
benutzt.
Die Priority Queue verändert sich wie folgt:
Benutzen von
Benutzen von
Prof. Dr. Dietmar Seipel
Erst jetzt wird 4 gelöscht, und wir besuchen
.
433
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Bei der Tiefensuche verändert sich Border dagegen wie folgt:
Löschen von
Benutzen von
Benutzen von
Benutzen von
Löschen von
In der Tat ist der Stack am Ende gleich
d.h. gleich dem inversen gefundenen Weg vom Start zum Ziel.
Prof. Dr. Dietmar Seipel
434
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Falls die Sackgasse bei
als die Tiefensuche.
Prof. Dr. Dietmar Seipel
länger wäre, so wäre die Breitensuche teurer
435
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Die Tiefensuche benutzt die Kanten in folgender Reihenfolge:
Die Breitensuche benutzt dagegen nur folgende Kanten:
Die Kanten zwischen 11 und 13 werden gar nicht benutzt.
Prof. Dr. Dietmar Seipel
436
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
In vielen praktischen Fällen werden sogar unterschiedliche Wege berechnet:
,
Tiefensuche:
Breitensuche:
Die Breitensuche brechnet immer einen kürzesten Weg, wenn man die
Kantenlängen alle auf 1 setzt.
In diesem Fall entspricht der Graphendurchlauf dem Algorithmus von
Dijkstra.
Prof. Dr. Dietmar Seipel
437
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Tiefensuche in Graphen mit Zyklen
Benutzung der Kanten:
(1,2), (2,3), (3,4), (4,5), (3,5), (3,6), (6,2), (6,5).
Die 5 unterstrichenen Kanten bilden einen Baum.
Prof. Dr. Dietmar Seipel
438
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Die weiteren Kanten heißen:
Vorwärtskanten:
Rückwärtskanten:
Prof. Dr. Dietmar Seipel
Seitwärtskanten:
439
Praktische Informatik I – Algorithmen und Datenstrukturen
8.3
Wintersemester 2006/07
Tiefensuche und Backtracking in P ROLOG
P ROLOG ermöglicht
deklarative Programmierung
kompakte Programme
rapid Prototyping
Die Auswertungsstrategie der SLDNF–Resolution benutzt
Tiefensuche
Backtracking
Unifikation
Prof. Dr. Dietmar Seipel
440
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Datenstrukturen in P ROLOG
P ROLOG–Atom: z.B. book, george, ‘George‘, x12op
Konstante: P ROLOG–Atom Number
z.B. book, 0, 123, 4
Variable: beginnend mit Großbuchstaben oder mit “_”
z.B. Book, Up, Var, _, _X
Funktor (Funktions– bzw. Prädikatensymbol):
Operator P ROLOG–Atom
z.B. +, –, , ancestor
Prof. Dr. Dietmar Seipel
Struktur: Konstante Variable Funktor(Struktur,
z.B. +(1,7), ancestor(bill,joe)
Listen sind spezielle Strukturen zum Funktor ’.’:
[a,b,c,d] = ’.’(a, [b,c,d])
+(1,7) ist äquivalent zu 1+7 (Infix–Notation).
, Struktur)
441
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
P ROLOG–Klauseln
(Prädikatensymbole: ancestor, parent, likes, woman, nice, loves)
"
#
!
:–
:–
Regeln: Kopf :– Rumpf, mit Konjunktion “,”, Disjunktion “;”
:–
Bedeutung:
Fakten:
!
!
#
Goal:
$
Prof. Dr. Dietmar Seipel
442
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Ein P ROLOG–Interpreter versucht ein Goal durch Inferenz zu beweisen.
Dies erfolgt Top–Down vom Goal ausgehend durch DFS–Durchlauf des
SLD–Baumes.
Beispiel:
?- likes(george,Y).
Y = mary
Yes
?- likes(X, Y).
X = george, Y = mary ;
X = mary, Y = george
Yes
?-
Prof. Dr. Dietmar Seipel
443
$
"
$
"
$
"
%$
#"
!
&
&
)
'
)
'
)
'
)
'
)
'
success
&
)*
'(
444
Prof. Dr. Dietmar Seipel
success
failure
failure
Wintersemester 2006/07
Praktische Informatik I – Algorithmen und Datenstrukturen
SLD–Baum
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Anfragen in P ROLOG
Die Auswertung von P ROLOG–Regeln erfolgt Top–Down mittels der
Methode der SLDNF–Resolution: d.h., aus einer Anfrage an das
Kopfatom einer Regel werden Unteranfragen an die Rumpfatome der
Regel erzeugt.
Dies entspricht dem Vorgehen bei der Abarbeitung von prozeduralen
Programmiersprachen.
Falls ein Rumpfatom mehrere Antworten liefert, so wird zuerst mit
einer solchen Antwort weitergerechnet (Tiefensuche); falls die
Berechnung später fehlschlägt, so kann mit der nächsten Antwort
fortgefahren werden (Backtracking).
In der Praxis sind viele P ROLOG–Prädikate aber funktional; d.h., aus
einer Eingabe wird genau eine Ausgabe erzeugt.
Prof. Dr. Dietmar Seipel
445
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Kontrollprimitive, welche über die PL1 hinausgehen:
“assert” und “retract” verändern die interne Datenbank von P ROLOG;
“clause” sucht in dieser.
“call” ruft Goals auf, die vorher zusammengebaut werden können.
Der Cut “!” friert die bisherige Variablenbelegung in der aktuellen
Regel ein.
“fail” ist ein Goal, das immer fehl schlägt.
Prof. Dr. Dietmar Seipel
446
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Literatur
W.F. Clocksin, C.S. Mellish:
Programming in P ROLOG, Springer, 1987.
I. Bratko: P ROLOG – Programming for Artificial Intelligence,
Addison–Wesley, Second Edition, 1990.
S. Ceri, G. Gottlob, L. Tanca:
Logic Programming and Databases, Springer, 1990.
J.W. Lloyd:
Foundations of Logic Programming, Springer, Second Edition, 1987.
Prof. Dr. Dietmar Seipel
447
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Listen sind spezielle P ROLOG–Strukturen mit dem binären Funktor ‘.’.
Liste: [a,b,c,d] = ’.’(a, ’.’(b, ’.’(c, ’.’(d, [ ]))))
Listenkonstruktion:
Falls X und Xs bereits gebunden (mit Werten belegt) sind, so ist [X|Xs]
die Liste, die man erhält, wenn man das Element X an die Liste Xs
vorne anhängt.
Für X = a und Xs = [b,c,d] ist [X|Xs] = [a,b,c,d].
Listenzerlegung:
Falls X und Xs ungebunden sind, so liefert der Aufruf [X|Xs] =
[a,b,c,d] die Belegungen X = a und Xs = [b,c,d]; man kann eine Liste
also in ihren Kopf X und den Rest Xs zerlegen.
leere Liste: [ ]
Prof. Dr. Dietmar Seipel
448
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Rekursion: das Prädikat member
/* member(?X, +L) <X is a member of the list L. */
member(X, [X|_]).
member(X, [_|Xs]) :member(X, Xs).
?- member(a, [c, b, a]).
Yes
Prof. Dr. Dietmar Seipel
449
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Relationales Programmieren
?- member(b, [a, b, c]).
Yes
?- member(X, [a, b, c]).
X = a;
X = b;
X = c
Yes
Beim Aufruf member(X, Y) sind X und Y nicht funktional voneinander
abhängig. Stattdessen realisiert member/2 eine n:m–Beziehung (Relation)
zwischen Listen und ihren Elementen.
Prof. Dr. Dietmar Seipel
450
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Das Prädikat member/2 definiert eine virtuelle Relation:
member
Element
List
a
[a, b, c]
b
[a, b, c]
c
[a, b, c]
a
[a, b]
Prof. Dr. Dietmar Seipel
451
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Suche in Graphen
_
/* graph_search(+Node, -Path) <*/
graph_search(X, Path) :graph_search(X, [X], Path).
graph_search(X, _, [X]) :graph_sink(X).
graph_search(X, Visited, [X|Path]) :( graph_edge(X, Y)
; graph_edge(Y, X) ),
not(member(Y, Visited)),
write(user, ’->’), write(user, Y),
graph_search(Y, [Y|Visited], Path).
Prof. Dr. Dietmar Seipel
452
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Labyrinth:
b
c
d
e
f
g
h
i
a
graph_edge(i,
graph_edge(i,
graph_edge(h,
graph_edge(g,
graph_edge(d,
graph_edge(d,
graph_edge(a,
graph_edge(b,
f).
h).
g).
d).
e).
a).
b).
c).
graph_source(i).
graph_sink(c).
Prof. Dr. Dietmar Seipel
453
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
?- graph_search(i, Path).
->f->h->g->d->e->a->b->c
Path = [i, h, g, d, a, b, c]
Yes
?- graph_search(e, Path).
->d->a->b->c
Path = [e, d, a, b, c] ;
->g->h->i->f
No
?-
Prof. Dr. Dietmar Seipel
454
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Das Prädikat graph_search/2 benutzt Tiefensuche, und es berechnet
einfache Pfade (ohne doppelte Knoten).
Beim Aufruf graph_search(Node, Path) mit einem gebundenen
Argument Node und einem freien Argument Path können alle
einfache Pfade von Node zu einer Senke (graph_sink) über
Backtracking berechnet werden.
Würde man eine weitere Kante graph_edge(e, b) in den Graphen
einfügen (die Wand zwischen e und b einreisen), so gäbe es einen
weiteren einfachen Pfad [e, b, c] von e zur Senke c.
Prof. Dr. Dietmar Seipel
455
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Man kann alle Antworten mittels Backtracking und findall/3 bestimmen:
...
graph_edge(e, b).
?- findall( Path,
graph_search(e, Path),
Paths ).
...
Paths = [ [e, d, a, b, c], [e, b, c] ]
Yes
?-
Prof. Dr. Dietmar Seipel
456
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Man kann mit P ROLOG (im Gegensatz zur “reinen” Logikprogrammierung)
auch
prozedural
mit Seiteneffekten und
mit globalen Variablen (realisiert mit Hilfe von assert und retract)
programmieren.
Es gibt umfangreiche Programmbibliotheken und Erweiterungen:
Datenstrukturen und Algorithmen, Kombinatorik,
Datenbank– und Web–Programmierung,
GUI–Programmierung, etc.
Prof. Dr. Dietmar Seipel
457
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Anwendungsbereiche:
regelbasierte Diagnosesysteme (Medizin, Technik)
symbolische Informationsverarbeitung, Parsing
Datenbanken mit komplexen Strukturen (Hierarchien, X ML)
Datenintegration
Semantic Web
Default Reasoning
kombinatorische Suchprobleme
(Graphenprobleme, Spiele wie Sudoku oder Minesweeper, etc.)
Prof. Dr. Dietmar Seipel
458
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Quicksort in P ROLOG
/* quicksort(List, Sorted_List) <*/
quicksort([], []) :!.
quicksort([X|Xs], Ys) :quicksort_divide(X, Xs, Xs1, Xs2),
quicksort(Xs1, Ys1),
quicksort(Xs2, Ys2),
append(Ys1, [X|Ys2], Ys).
Prof. Dr. Dietmar Seipel
459
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
quicksort_divide(X, Xs, Xs1, Xs2) :findall( X1,
( member(X1, Xs),
X1 < X ),
Xs1 ),
findall( X2,
( member(X2, Xs),
X2 > X ),
Xs2 ).
append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :append(Xs, Ys, Zs).
Prof. Dr. Dietmar Seipel
460
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Mergesort in P ROLOG
/* mergesort(List, Sorted_List) <*/
mergesort(Xs, Xs) :length(Xs, N),
N =< 1,
!.
mergesort(Xs, Ys) :middle_split(Xs, Xs1, Xs2),
mergesort(Xs1, Ys1),
mergesort(Xs2, Ys2),
mergesort_merge(Ys1, Ys2, Ys).
Prof. Dr. Dietmar Seipel
461
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
mergesort_merge([], Xs, Xs) :!.
mergesort_merge(Xs, [], Xs) :!.
mergesort_merge([X1|Xs1], [X2|Xs2], [X|Xs]) :( X1 < X2,
X = X1,
mergesort_merge(Xs1, [X2|Xs2], Xs)
; X = X2,
mergesort_merge([X1|Xs1], Xs2, Xs) ).
Prof. Dr. Dietmar Seipel
462
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Binäre Suchbäume in P ROLOG
/* search_in_binary_tree(Key, Tree) <*/
search_in_binary_tree(Key, Tree) :binary_tree_parse(Tree, Key, _, _).
search_in_binary_tree(Key, Tree) :binary_tree_parse(Tree, Root, Left, Right),
( ( Key < Root,
!,
Tree = Left )
; ( Key > Root,
Tree = Right ) ),
search_in_binary_tree(Key, Tree).
Prof. Dr. Dietmar Seipel
463
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Kapselung des Zugriffs:
/* binary_tree_empty(Tree) <*/
binary_tree_empty(Tree) :( dislog_variable_get(binary_tree_mode, xml),
Tree = node:[]:[]
; Tree = [] ).
Prof. Dr. Dietmar Seipel
464
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
/* binary_tree_parse(Tree, Key, Lson, Rson) <*/
binary_tree_parse(Tree, Key, Empty, Empty) :binary_tree_empty(Empty),
( dislog_variable_get(binary_tree_mode, xml),
Tree = node:[key:Key]:[]
; Tree = [Key] ),
!.
binary_tree_parse(Tree, Key, Lson, Rson) :( dislog_variable_get(binary_tree_mode, xml),
Tree = node:[key:Key]:[Lson, Rson]
; Tree = [Key, Lson, Rson] ).
Prof. Dr. Dietmar Seipel
465
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Suchbaum in X ML–Darstellung:
<node key="8">
<node key="4">
<node key="2">
<node key="1"/>
<node key="3"/>
</node>
<node key="6">
<node key="5"/>
<node key="7"/>
</node>
</node>
<node key="12">
<node key="10">
<node key="9"/>
<node key="11"/>
</node>
<node key="13"/>
</node>
</node>
Prof. Dr. Dietmar Seipel
466
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
Suchbaum
X ML–Darstellung:
<node key="2">
<node key="1"/>
<node key="3"/>
</node>
P ROLOG–Darstellung:
node:[key:2]:[
node:[key:1],
node:[key:3] ]
alternative P ROLOG–Darstellung:
[ 2,
[1],
[3] ]
Prof. Dr. Dietmar Seipel
467
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
/* insert_into_binary_tree(Key, Tree, New_Tree) <*/
insert_into_binary_tree(Key, Tree, New_Tree) :binary_tree_parse(Tree, Root, Left, Right),
( ( Key = Root, % Key is already in Tree
New_Tree = Tree )
; ( Key < Root,
insert_into_binary_tree(Key, Left, L),
binary_tree_parse(New_Tree, Root, L, Right) )
; ( Key > Root,
insert_into_binary_tree(Key, Right, R),
binary_tree_parse(New_Tree, Root, Left, R) ) ).
insert_into_binary_tree(Key, Tree, New_Tree) :binary_tree_empty(Tree),
binary_tree_parse(New_Tree, Key, Tree, Tree).
Prof. Dr. Dietmar Seipel
468
Praktische Informatik I – Algorithmen und Datenstrukturen
Wintersemester 2006/07
/* keys_to_binary_tree(Keys, Tree) <*/
keys_to_binary_tree(Keys, Tree) :binary_tree_empty(Empty),
insert_into_binary_tree_(Keys, Empty, Tree).
/* insert_into_binary_tree_(Keys, Tree, New_Tree) <*/
insert_into_binary_tree_([], Tree, Tree).
insert_into_binary_tree_([Key|Keys], Tree, New_Tree) :insert_into_binary_tree(Key, Tree, Tree_2),
insert_into_binary_tree_(Keys, Tree_2, New_Tree).
Prof. Dr. Dietmar Seipel
469
Herunterladen