Binäre Suchbäume
Binäre Suchbäume dienen der effizienten Implementierung von sogenannten
DICTIONARIES,
das sind Datentypen zur Darstellung von Mengen, welche die Operationen
INSERT, DELETE und MEMBER, also Einfügen eines Elementes, Löschen
eines Elementes und den Test auf "Enthaltensein" eines Elementes zu
Verfügung stellen.
Alle drei Algorithmen für INSERT, DELETE und MEMBER folgen jeweils
einem einzigen Pfad im Baum von der Wurzel zu einem Blatt oder zu einem
inneren Knoten. Der Aufwand ist proportional zu der Länge dieses
Pfades. Bekannterweise ist die maximale Pfadlänge in einem balancierten
Baum O(log n) und O(n) in einem degenerierten Baum, wobei n hier die
Anzahl der Knoten des Baumes ist.
Ein degenererierter Baum entsteht z.B. wenn die Folge der einzufügenden
Knoten bereits sortiert vorliegt.
Im folgenden Script wurden die drei
Operationen in perl implementiert.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;;
# search for $x in tree $t. If $x is found,
# returns 1, otherwise returns 0
sub member {
my ($t,$x) = @_;
if (!defined($t)) { return 0;}
elsif ($x eq $t->{key}) { return 1;}
elsif ($x le $t->{key}) { return &member($t->{left},$x) }
else { return &member($t->{right},$x) } # $x > $t->{key}
}
# search for $x in tree $t. If $x is found, returns node
# containing $x1, otherwise returns undef
sub find {
my ($t,$x) = @_;
if (!defined($t)) { return undef;}
elsif ($x eq $t->{key}) { return $t;}
elsif ($x le $t->{key}) { return &member($t->{left},$x) }
else { return &member($t->{right},$x) } # $x > $t->{key}
}
# insert $element $x in tree $t
sub insert {
my $t = \$_[0];
my $x = \$_[1];
if (!defined($$t)) {
# empty tree, create node andinsert $x in it
$$t = {};
$$t->{key} = $$x;
$$t->{left} = undef;
$$t->{right} = undef;
} else {
# if element not already in tree
if ($$t->{key} ne $$x) {
# insert element in the correct subtree
if ($$t->{key} gt $$x) {
&insert($$t->{left},$$x);
} else {
&insert($$t->{right},$$x);
}
}
}
}
# create a file suitable for "dot"
sub traverse {
my ($t) = @_;
if (!defined($t)) { return undef;}
if (defined $t->{left}) {
print $t->{key}." -> ".$t->{left}->{key}."\n";
&traverse($t->{left});
}
if (defined $t->{right}) {
print $t->{key}." -> ".$t->{right}->{key}."\n";
&traverse($t->{right});
}
}
sub print_graph {
print EOT;
digraph hierarchy {
//nodesep=1.0 // increases the separation between nodes
node [color=black,fontcolor=black]
edge [color=black] //setup options
EOT
&traverse($_[0]);
print EOT;
}
EOT
}
# main program
my $tree = undef;
#srand (time ^ $$);
#foreach (1 .. 12) {&insert($tree, int(rand 100))}
foreach (
qw(Binaere Suchbaeume dienen der
Implementierung von DICTIONARIES)) {
&insert($tree,lc $_);
}
&print_graph($tree);
Im obenstehenden Script wird ein kleiner Beispieltext Wort für
Wort in einen binären Suchbaum eingefügt. Das Bild links
zeigt den dadurch erzeugten Baum.
Die Subroutine print_graph gibt den Baum dann im dot-Format aus. Damit kann beispielsweise eine graphische Darstellung des Baumes wie die nebenstehende im gif-oder PostScript-Format erzeugt werden.
