Keine einheitliche Lösung verfügbar.
Der einfache Fall ist der des leeren Baumes, der nämlich keinen
Knoten enthält:
no_of_nodes( nil, 0).
Die Rekursion läuft über die Teilbäume, die an einem
Knoten hängen. Beachten Sie, daß hier zum ersten Mal in den
Übungen eine nichtlineare Rekursion vorliegt.
no_of_nodes( node( _, Left, Right), No) :- no_of_nodes( Left, LeftNodes), no_of_nodes( Right, RightNodes), No is LeftNodes + RightNodes + 1.
an beachte außerdem, daß dieses Prädikat nur sehr beschränkt dazu geeignet ist, binäre Bäume zu produzieren.
Auch hier wieder der einfache Fall zuerst: Wenn der Ursprungsbaum leer
ist, dann besteht der neue Baum aus genau einem Knoten, nämlich dem,
der eingefügt wurde.
insert_name( nil, Name, node( Name, nil, nil)).
Schwieriger wird es, wenn der zu betrachtende Knoten nicht leer ist.
Dann müssen drei Fälle betrachtet werden. Falls der einzufügende
Name kleiner als der Schlüssel des Knotens ist, muß in den linken
Teilbaum eingefügt werden. Ist er größer als der Wert,
muß rechts eingefügt werden. Ist er gleich, so passiert überhaupt
nichts.
insert_name( node( Key, OldLeft, Right), Name, node( Key, NewLeft, Right)) :- Name @< Key, insert_name( OldLeft, Name, NewLeft). insert_name( node( Key, Left, OldRight), Name, node( Key, Left, NewRight)) :- Name @> Key, insert_name( OldRight, Name, NewRight). insert_name( node( Key, Left, Right), Key, node( Key, Left, Right)).
Die außerlogischen Prädikate assert und retract
können dazu benutzt werden, die eingegebenen Daten dauerhaft in der
Datenbasis zu verankern.
mytree(nil). insert_into_tree( Name) :- retract( mytree( Tree)), insert_name( Tree, Name, NewTree), assert( mytree( NewTree)), write( NewTree).
Normalerweise würde man sagen, die Komplexität der Suche in binären Bäumen ist logarithmisch. Warum? Auf der ersten Stufe befindet sich ein Knoten, auf der zweiten Stufe vier, auf der dritten Stufe acht, etc. Auf der n-ten Stufe befinden sich 2^(n-1) Knoten. Ein baum der Höhe h hat folglich 1+2+4+...+2^(n-1) = 2^n-1 Knoten, für deren Absuchen aber nur n Operationen erforderlich sind. Andersrum: Hat ein baum k Knoten, so sind log(k) Operationen zu dessen Absuchen notwendig.
Der lineare Fall tritt auf, wenn einer der Teilbäume an jedem Knoten
leer ist (ein sog. entarteter Baum). Man kann ihn z.B. durch folgende Anfragen
erzeugen:
insert_into_tree( gustav). insert_into_tree( marion). insert_into_tree( monika). insert_into_tree( ortrud). insert_into_tree( stefan). insert_into_tree( tamara). insert_into_tree( viktor). insert_into_tree( vogon).
Der erzeugte Baum sieht dann so aus:
node(gustav, nil, node(marion, nil, node(monika, nil, node(ortrud, nil, node(stefan, nil, node(tamara, nil, node(viktor, nil, node(vogon, nil, nil))))))))
er entspricht damit eher einer Liste als einem vernünftigen Baum. Das kann man verhindern, indem man fordert, daß die Anzahl der Knoten auf der linken und rechten Seite eines Knotens immer ungefähr gleich sind. Das Ergebnis davon sind sog. ausgeglichene Suchbäume. Mehr dazu z.B. in Wirth; Algorithmen und Datenstrukturen.
Author: | Jan W. Amtrup |
Document: | |
Last modified: |