www.mucker.at http://www.mucker.at Helmut Mucker de Binäre Suchbäume http://www.mucker.at/2008//07#binarytree_pl <!-- amazon-search: Algorithmen Datenstrukturen --> <!-- amazon-mode: books --> <p> 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. <!-- amazon_textlink:3897211416 --> <br><br> <!-- asin:3897211416 --> 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.<br clear="all"> <br> Im folgenden Script wurden die drei Operationen in <b>perl</b> implementiert. <pre> #!/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); </pre> <img border="1" src="/images/binarytree.png" width="236" height="342" alt="" align="left" style='margin-right:10px;'> 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. <br><br> Die Subroutine <b>print_graph</b> gibt den Baum dann im <b>dot</b>-Format aus. Damit kann beispielsweise eine graphische Darstellung des Baumes wie die nebenstehende im <b>gif</b>-oder <b>PostScript</b>-Format erzeugt werden. <br clear="all"> </p>