teil iii : bäume - mathematik.uni-ulm.de · 3 repeat pop until (: alle operatoren auf dem stack...

31
1 Teil III : Bäume § Was ist ein Baum? § Termbäume § Repräsentation allgemeiner Bäume § Travesieren von Bäumen § Binäre Suchbäume K. Murmann, H. Neumann, Fakultät für Informatik, Universität Ulm, 2001 1. Was ist ein Baum? Stammbaum Definitionen Begriffe & Eigenschaften (Teil 1) Anwendung von Bäumen Begriffe & Eigenschaften (Teil 2)

Upload: trankhuong

Post on 14-Aug-2019

219 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

1

Teil III : Bäu m e

§ Was ist ein Baum?

§ Termbäume

§ Repräsentation allgemeiner Bäume

§ Travesieren von Bäumen

§ Binäre Suchbäume

K. Murmann, H. Neumann, Fakultät für Informatik, Universität Ulm, 2001

1. Was ist ein Baum?

• Stammbaum• Definitionen• Begriffe & Eigenschaften (Teil 1)• Anwendung von Bäumen• Begriffe & Eigenschaften (Teil 2)

Page 2: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

2

Der Stammbaum einer Person besteht aus einem Knoten mit den Daten dieser Person, an den zwei wei tere Stammbäume angehängt s ind: der Stammbaum des Vaters und der Stammbaum der Mutter

Stammbaum

Dieser Baum ist ein Binärbaum , denn jeder Knoten besitzt zwei Nachfolger

In einem Binärbaum besitzt jeder Knoten maximal zwei Nachfolger

Definition 1:Ein Baum T mit Elementen eines Typs ist entweder leer oder er besteht aus einem Element (Knoten, Node), verknüpft (Kante(n), Edge(s)) mit einer endlichen Anzahl disjunkter Bäume.

Definition(en)

Definition 2:Ein Baum T ist eine endliche Menge N mit Elementen eines Typs mit folgenden Eigenschaften:

Ø die Menge N ist entweder leer oder

Ø es gibt ein ausgezeichnetes Element, die sog. Wurzel (root) des Baumes T

Ø die übrigen Elemente zerfallen in disjunkte Mengen, die ebenfalls Bäume bilden

Page 3: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

3

Beispiel:

Knotenmenge (Nodes): N = {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p}

Baum (Tree): T = {a, {b, {d, {i}}, {e, {j}, {k}, {l}}}, {c, {f, {o}}, {g, {m}, {n}}, {h, {p}}}}

T = {a, {b, {d, {i}}, {e, {j}, {k}, {l}}}, {c, {f, {o}}, {g, {m}, {n}}, {h, {p}}}}

Definition 3:

Ein Baum T ist ein Tupel

T = (N, E)

mit der Menge N von Knoten(-punkten)

und der Menge E der Kanten(-linien)

∞<≤Ν∈= )(0},|{ NcardinN i

NNE ×⊆

Page 4: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

4

Begriffe & Eigenschaften (Teil 1)

Ø Ein besonderer Knoten ist die Wurzel (root) r: sie besitzt - im Gegensatz zu einem „normalen“ Knoten - keinen Vorgänger (parent) p sondern nur 0 ... k Nachfolger (children) c i

p

r

r

c

p

cX (p,c) ∈ Ep

c1 c2 c3 ck...Geschwister (siblings)

Wurzel (root) r:

Vorgänger (parent) p,Nachfolger (children) c i

Geschwister:

1)(},),(:|{ =∈∈∃= RcardErpNprR

}),(|{}{ 1 EcpNccccS iiikp ∈∧∈== K

ii cpchildpcparent

EcppcardRNc

===∈∈∀

)(,)(

1})),(|({:\}

Ø Jeder Knoten ausser der Wurzel hat genau einen parent (Vorgänger)

Ø Ein Baum ist zusammenhängend, d.h. man kann von einem beliebigen Knoten aus über eine Folge von parent-Knoten zur Wurzel „aufsteigen“. Ein „Aufstieg“ oder „Abstieg“ im Baum über m Knoten hinweg heisst Pfad mit Länge m-1.Die Höhe h eines Knotens ist die Länge des Pfades von der Wurzel bis zu diesem Knoten. Für jeden Knoten gibt es genau 1 Pfad von der Wurzel zu diesem Knoten. Die Höhe h des Baumes ist der längst-mögliche Pfad im Baum, also das Maximum aller Höhen.

Ø Ein „normaler“ Knoten (mit Vorgänger und Kind(ern)) heisst innerer Knoten, ein Knoten ohne Kind(er) heisst Blatt. Der Grad eines Knotens ist die Anzahl seiner Kinder. Ein Blatt besitzt

also den Grad 0 (deg(p)=0 ⇔ Knoten p ist Blatt). Der Grad eines Baumes T ist das Maximum der Knotengrade. Ist deg(T) ≤≤ 2, so ist T ein Binärbaum, ist deg(T) > 2, so ist T ein Mehrweg-/Vielwegbaum.

Page 5: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

5

Ø Die Menge aller Kinder eines Knotens n bilden zusammen mit n denTeilbaum mit Wurzel n

Ø Ein Baum T heisst der Höhe nach ausgeglichen (height balanced), wenn die Höhe aller Teilbäume zu einem Knoten n (= Wurzel zu diesen Teilbäumen) sich maximal um 1 unterscheidet.Ein Baum T heisst dem Gewicht nach ausgeglichen (weight balanced) oder auch vollständig ausgeglichen, wenn sich die Teilbaum-Knoten-Anzahlen aller Teilbäume zu einem Knoten n (= Wurzel zu diesen Teilbäumen) maximal um 1 unterscheidet.

height balanced weight balanced

Anwendung von Bäumen

Ø UNIX-Dateisystem. Dieses ist im Prinzip ein Vielweg-Baum, dessen Kanten über die Links hergestellt sind.

Ø Datenorganisation (→ Zugriffsbeschleunigung)Die sortierte Datenmenge einer Datei sei im Hauptspeicher in einem „sortierten“ Baum abgelegt:

Page 6: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

6

Für jeden Knoten gilt: Im linken Teilbaum nur kleinere, im rechten nur grössere Elemente.

(Binär-)Suche nach Element x: Vergleiche x mit Wurzel, falls grösser, dann rechter Teilbaum, falls kleiner, dann linker Teilbaum u.s.w.

Höhe des Baumes best immend für maximale Suchzeit; deshalb sollte der Baum möglichst ausgeglichen sein.

Suche, ob k in Datenmenge enthalten: k<m → k>g → k=k → k enthalten

Suche, ob z in Datenmenge enthalten: z>m → z>q → z>t → z≠v → z nicht enthalten

Ø Decodier(binär)baum für Morsezeichen

Page 7: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

7

Begriffe & Eigenschaften (Teil 2)

Ø In geordnete Bäumen sind die Kinder-Knoten (Geschwister) eines parent-Knotens in einer zugewiesenen „horizontalen“ Ordnung sortiert.

p

c1 c2 c3 ck...zugewiesene Ordnung

Ø Ein ganzer Binärbäumen ist ein Binärbaum, bei dem alle Knoten mit weniger als 2 Kindern durch Blätter „binär ergänzt“ wurden; alle ursprünglichen Knoten sind dann innere Knoten (deg = 2), die Blätter sind alle vom Grad deg = 0. Der ganze Binärbaum muss nicht ausgeglichen sein.

Ø Ein vollständiger Binärbaum ist ein optimal ausgeglichener, ganzer

Binärbaum, alle möglichen Pfade Blatt → Wurzel sind gleich lang (= Höhe h des Baums)

Dieser vollständige Binärbaum (jeder Knoten 2 Kinder) besitzt:♣ 2h Blätter (hier 23= 8)♣ 20 + 21 + ... 2h-1 = geometr. Reihe = (2h - 1)/(2-1) = (2h - 1) innere Knoten

Höheh = 3

Tiefe

0

1

2

3

Ø Ein vollständiger k-stelliger Baum (jeder Knoten k Kinder) besitzt: ♣ Anzahl Blätter = kh

♣ Anzahl innerer Knoten = k0 + k1 + ... kh-1 = geometr. Reihe = (kh - 1)/(k-1)♣ eine Höhe h = logk(Anzahl Blätter)

Page 8: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

8

1. Term-Bäume

• Notation arithmetischer Ausdrücke• Transformation eines arithmetischen Ausdrucks in

Postfix-Notation• Generierung von Analyse-Bäumen („parse-trees)

Notation arithmetischer Ausdrücke

Ø Infix-Notationist Standard-Notation mathematischer Ausdrücke

• 1-stelligen Operatoren: <aus> = <op><operand><op> = + | –

• 2-stellige Operatoren: <aus> = <operand><op><operand><op> = + | – | • | /

• Strukturierung durch Klammern: ( | )

Ø Präfix-Notation für• 2-stellige Operatoren: <aus> = <op><operand><operand>

Ø Postfix-Notation für• 2-stellige Operatoren: <aus> = <operand><operand><op>• keine Strukturierung durch Klammern notwendig!!

→→ maschinelle Auswertung

Page 9: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

9

+ –

A B C D

Ø Baum-Notation:

Beispiel:

Ø Infix-Notation: (A + B) • (C – D)

Ø Präfix-Notation: • + A B – C D

Ø Postfix-Notation: A B + C D – •

Transformation eines arithmetischen Ausdrucks in Postfix-Notation

Ø Der arithmetische Ausdruck sei in Infix-Notation gegeben (Standard-Notation)

A + (B – C)/D

Ø shunting-yard algorithm (Verschiebebahnhof-Algorithmus)

Page 10: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

10

Ø Regeln des shunting-yard algorithmDie Zeichenfolge des Ausdrucks wird von rechts nach l inks bewegt; dabei wird jedes Symbol individuell evaluiert nach 5 Regeln:

1 Transfer: Operanden (am Anfang des Eingabestrings) →→ in Ausgabestring

2 push: linke (öffnende) Klammer →→ auf stack

3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer →→ in Ausgabestring; dann werden beide Klammern gelöscht.

4 WHILE priority(top) >= operator DO pop: Operatoren auf dem Stack →→ in Ausgabestring bis das oberste Stack-Element von geringerer Priorität ist.

(steigende Priorität: ( →→ + – →→ • / )Falls Stack leer oder oberstes Stack-Element von geringerer Priorität, dann Operator →→ auf Stack (push)

5 WHILE NOT stack_empty DO pop: Input string leer ⇒⇒ alle Elemente auf Stack →→ Ausgabestring

Page 11: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

11

Generierung von Analyse-Bäumen („parse-trees)

Ø arithmetische Ausdrücke: duale Operanden ⇔⇔ binäre Bäume

Ø Infix- & Postfix-NotationInfix: A • (((B + C) • (D • E) ) + F) ← für uns

Postfix: A B C + D E • • F + • ← für den Rechner mit Stack

Ø Analysebaum •

A +

• F

+ •

B C D E

Page 12: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

12

Aufbau eines Analysebaums aus einer Eingabe in Postfix-Notation

TYPELINK = POINTER TO NODE;NODE = RECORD

info : CHAR;left, right : LINKEND;

VARx, z : LINK;c : CHAR;

PROCEDURE createLeaf() : LINK;VARleaf : LINK;

BEGINNEW(leaf);leaf^.left := leaf;leaf^.right := leaf;RETURN leaf

END createLeaf;

inforight

left

link

left

right

leaf

BEGINstackInit;z := createLeaf();

REPEATREPEATReadChar(c)

UNTIL c <> ; (* skip blanks *)

NEW (x);x^.info := c;IF (c = '*') OR (c = '+') THENx^.right := pop;x^.left := pop

ELSEx^.right := z;x^.left := z

END;

push(x)UNTIL EOLN

END ....

z

x

x

z

Page 13: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

13

1. Repräsentation al lgemeiner Bäume

• allgemeine Bäume• reine bottom-up Baumbearbeitung• reine top-down Baumbearbeitung

Page 14: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

14

Allgemeine Bäume

Ø Allgemeine Bäume besitzen Knoten mit variabler Anzahl von Kind-Knoten

Ø Die Repräsentation bestimmt die Art der Operationen und umgekehrt

reine bottom-up Baumbearbeitung

Ø Bäume, die nur von den Blättern aufwärts (bottom-up) bearbeitet werden

Ø Für jeden Knoten wird nur der Verweis zum parent-Knoten repräsentiert

parent

RECORDelem : elemtype;parent := LINK

END

Hinweis : Die Wurzel r zeigt auf sich selbst

r

Page 15: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

15

Ø Einfache und effiziente Realisierung mittels Feldern:

info[.] : Information, z.B. Zeichenparent[.] : Index des parent-Knoten

Ø Beispiel:

E

T

A

M LP

A S

R E

E

1 2

3

4 5 6 7

8

9 11

10

k : 1 2 3 4 5 6 7 8 9 10 11

info[k] : A S A M P L E T R E E

parent[k] : 3 3 10 8 8 8 8 9 10 10 10

reine top-down Baumbearbeitung

Ø Verwaltung von Kind-Knoten ohne vorherige Allokation einer spezif ischen (maximalen) Anzahl.⇒⇒ verkettete Liste für Repräsentation der Knoten (variable Anzahl)

Ø Konzept: Knoten des Baums haben genau 2 Zeiger:♠ Zeiger L(inks) zum 1. (am weitesten links stehenden) Kind-Knoten♠ Zeiger R(echts) zu den (eigenen) Geschwister-Knoten♠ Der letzte Geschwister-Knoten zeigt zurück auf parent-Knoten

(→ Schleifen)

n

c

s1 ..... sk

Geschwister s1 ...sk von n

p

Page 16: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

16

Ø Frage: Gibt es einen Unterschied zwischen dieser (Baum-)Struktur und binären Bäumen?

Antwort: Nein

Ø Beispiel:

E

T

A

M LP

A S

R E

E

E

T

A

M

L

P

A

S

R

E

E

1. Traversieren von Bäumen

• Traversieren von Bäumen allgemein• Strategie pre-order• Strategie in-order• Strategie post-order• Strategie level-order

Page 17: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

17

Traversieren von Bäumen allgemein

Ø Travesieren eines Baumes bedeutet das systematische Absuchen eines Baumes, wobei jeder Knoten „besucht“ wird (visit). „Besuchen“steht für: auslesen, einlesen, vergleichen, markieren, ...

Ø Hier: elementare Operationen auf Binärbäumen

Ø Beispielbaum:

E

T

A

M L

P

A

S

R

E

E

Strategie pre-order

Ø Rekursive Strategie:

Wurzel → l inker Teilbaum → rechter Teilbaum

E

T

A

M L

P

A

S

R

E

E

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

visit(t);traverse(t^.L);traverse(t^.R)

ENDEND traverse;

z ist Zeiger auf Blatt

Knotenfolge:

Rekursionstiefe:

E

6

A

4

A

4

S

3

M

2

P

1

E

5

T

5

R

4

E

3

L

2

visit(t) zuerst

Page 18: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

18

TYPELINK = POINTER TO NODENODE = RECORD

elem : <elemtype>;L, R : LINK (* Verzweigung L(eft) & R(ight*)

END

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

visit(t);traverse(t^.L);traverse(t^.R)

ENDEND traverse;

PROCEDURE traverse (t : LINK);

BEGIN push(t) WHILE NOT stack_empty DO

t := pop; visit(t);IF (t^.R <> z) THEN

push(t^.R) END; IF (t^.L <> z) THEN

push(t^.L) END

END

END traverse;

Ø nicht­rekursive Pre-Order-Traversierung → Stack­basierte Lösung

(Annahme: Stack­Initialisierung außerhalb der Prozedur !)

Travesiere rechts

Travesiere links

pre-order

Page 19: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

19

t

t^.L

t^.R

t^.L^.L

t^.L^.R

t^.R

t^.R

t^.L^.R

t^.R

visit(t) visit(t^.L) visit(t^.L^.L)

visit(t^.L^.R) visit(t^.R)

t

t^.Rt^.L

t^.L^.L

t^.L^.R

Ø Beispiel:

Strategie in-order

Ø Rekursive Strategie:

l inker Teilbaum → Wurzel → rechter Teilbaum

E

T

A

M L

P

A

S

R

E

E

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

traverse(t^.L);visit(t); traverse(t^.R)

ENDEND traverse;

z ist Zeiger auf Blatt

Knotenfolge:

Rekursionstiefe:

A

4

S

3

A

4

M

2

P

1

E

6

E

5

T

5

R

4

E

3

L

2

visit(t) in der Mitte

Page 20: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

20

TYPELINK = POINTER TO NODENODE = RECORD

elem : <elemtype>;L, R : LINK (* Verzweigung L(eft) & R(ight*)

END

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

traverse(t^.L);visit(t);traverse(t^.R)

ENDEND traverse;

Sonderfall 2

Sonderfall 1

Ø nicht­rekursive In-Order-Traversierung → Die stack­basierte Lösung ist

ein Beispiel dafür, dass die rekursive Programmierung viel eleganter ist (aber auch langsamer). In der stack­basierten Lösung sind 2 Sonder-fälle zu berücksichtigen.

Page 21: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

21

Strategie post-order

Ø Rekursive Strategie:

l inker Teilbaum → rechter Teilbaum → Wurzel

E

T

A

M L

P

A

S

R

E

E

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

traverse(t^.L);traverse(t^.R);visit(t)

ENDEND traverse;

z ist Zeiger auf Blatt

Knotenfolge:

Rekursionstiefe:

E

6

S

3

A

4

M

2

A

4

P

1

E

5

T

5

R

4

E

3

L

2

visit(t) zuletzt

TYPELINK = POINTER TO NODENODE = RECORD

elem : <elemtype>;L, R : LINK (* Verzweigung L(eft) & R(ight*)

END

PROCEDURE traverse(t: LINK)

BEGINIF t <> z THEN

traverse(t^.L);traverse(t^.R);visit(t)

ENDEND traverse;

Page 22: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

22

Strategie level-order

Ø Nicht-rekursive Strategie:

oben → unten und auf jedem level links → rechts

E

T

A

M L

P

A

S

R

E

E

Knotenfolge: EAASMP ETREL

PROCEDURE traverse (t : LINK);

BEGIN enqueue(t) WHILE NOT queue_empty DO

t := dequeue(t); visit(t);IF (t^.L <> z) THEN

enqueue(t^.L) END; IF (t^.R <> z) THEN

enqueue(t^.R) END

END

END traverse;

Ø nicht­rekursive Level-Order-Traversierung → Queue­basierte Lösung

es existiert keine offensichtliche rekursive Lösung!

Ø Anpassung der (nicht-rekursiven, stack-orientierten) Pre-Order-Prozedur:

Page 23: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

23

t

t^.Rt^.L

t^.L^.L

t^.L^.R

Ø Beispiel:

oben rein

Queue!

unten raus

1. Binäre Suchbäume

• Struktur• Aufwand• Implementierung des Baums• Einfügen eines Knotens• Löschen eines Knotens

Page 24: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

24

Struktur

Ø Problem: Eine Menge von INTEGER/CARDINAL-Zahlen (oder an-deren Elementen, für die eine Ordnung gilt) soll eingelesen und so abgespeichert werden, dass für weitere Elemente möglichst schnell entschieden werden kann, ob diese zur eingelesenen Menge gehören oder nicht.

Ø Lösung: Die einzulesende Menge wird in einer binären Baumstrukturabgelegt, sodass jeder Knoten ein Element enthält und für jeden Teilbaum gilt:

Elemente im < Wurzelelement < Elemente imlinken Tei lbaum rechten Teilbaum

Ø Suchbaum

Ø Beispiel:

25

8 32

5 13 30 38

2 6 11 19 26 31 36 41

Aufwand

Ø Gegeben: Ein vollständiger Binärbaum T und eine Zahl x, die als Suchschlüssel dient.

Ø Verfahren:1 Vergleich von x mit Wurzelelement, wenn gleich, dann gefunden →→ fertig

2 wenn kleiner, suche im linken Teilbaum, wenn grösser, suche im rechten Teilbaum

3 falls x nicht gefunden wurde bis das erste Blatt erreicht wurde, ist x im Suchbaum nicht enthalten

Ø Aufwand im schlechtesten Fall (Durchsuchen der gesamten Höhe des Baumes) bei n Knoten:

♠ vollständiger Baum: ld(Anzahl Blätter) = ld (n+1) Suchschritte♠ entarteteter Baum (lineare Liste): n Suchschritte

Page 25: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

25

Implementierung des Baumes

Ø Struktur:

TYPE elemtype = CARDINAL; LINK = POINTER TO NODE; NODE = RECORD

elem : elemtype; parent, L, R : LINK

END;

VAR el : elemtype;

tree, newNode : LINK;

Elemente sind Zahlen

Ø Einlesen von Elementen und Generierung von Knoten des Baumes

newNode

Einfügen eines Knotens(siehe nächste Folie)

: tree := NIL; el := 1; (* Abbruchwert = 0 *)

WHILE el <> 0 DO ReadCard(el); IF el <> 0 THEN NEW(newNode); newNode^.elem := el; newNode^.parent := newNode; newNode^.L := NIL; newNode^.R := NIL; InsertNode(newNode, tree)

END END;

:

Page 26: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

26

In der 1. Suchrunde:vorläufiger parent = Wurzel

Ø Nicht-rekursiver Algorithmusgegeben sind: Zeiger x auf neuen Knoten und Zeiger tree auf Baum(wurzel)

♣ der neue Knoten newNode wurde im letzten Programm erzeugt und mit einem Element el versehen. Der parent-Zeiger zeigt auf newNode selbst, L- und R-Zeiger auf NIL. Der neue Knoten soll mittels InsertNode(newNode, tree) in den Baum eingefügt werden.

♣ If der Baum noch leer ist (tree=NIL), then wird der neue Knoten zur Wurzel (tree:=x), (fertig!), else zeigt dessen parent-Zeiger vorläufig auf die Wurzel (par := tree) und die Bool‘sche Variable nodeInsert wird auf FALSE gesetzt, d.h. der neue Knoten ist noch nicht im Baum plaziert.

♣ Suche nach der richtigen Posit ion des neuen Knotens im Baum:

♥ Vergleich der Elemente: if Knotenelement < parent-Element then Einbau des Knotens in den l inken Teilbaum des vorläufigen parent (else in dessen rech-ten Teilbaum).

♥ If der l inke Zeiger des vorläufigen parent bereits auf einen Knoten zeigt (par^.L<>NIL), then wird dieser zum neuen vorläufigen parent (par:=par^.L) und es geht von vorne los mit Elemente-Vergleich (while (NOT nodeInsert) -Schleife), else - Platz ist noch leer - wird der Knoten dort eingebaut: par^.L:=x; x^.parent:=par; nodeInsert.=TRUE (fertig!)

Einfügen eines Knotens

PROCEDURE InsertNode(x : LINK; VAR tree : LINK);

VAR par : LINK; nodeInsert : BOOLEAN;

BEGIN IF tree = NIL THEN (* leerer Baum *)

tree := x (* parent(x) = x *) ELSE

par := tree, nodeInsert := FALSE;

WHILE (NOT nodeInsert) DO IF (x^.elem < par^.elem) THEN

IF (par^.L <> NIL) THEN par := par^.L ELSE par^.L := x;

x^.parent := par; nodeInsert := TRUE

END ELSE

IF (par^.R <> NIL) THEN par := par^.R ELSE par^.R := x;

x^.parent := par; nodeInsert := TRUE

ENDEND (* IF *)

END (* WHILE *) END (* IF *)

END InsertNode;

Baum leer → Knoten x ist Wurzel

Baum nicht leer → Wurzel ist (vorläufiger) parent

Einbau von x in li. Teilbaum des (vorl.) parent

Einbau von x in re. Teilbaum des (vorl.) parent

WHILE-Schleife läuft, bis Knoten x eingebaut

Page 27: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

27

Ø Rekursiver Algorithmusgegeben sind: Zeiger x auf neuen Knoten und Zeiger tree auf Baum(wurzel)

♣ der neue Knoten newNode wurde im letzten Programm erzeugt und mit einem Element el versehen. Der parent-Zeiger zeigt auf newNode selbst, L- und R-Zeiger auf NIL. Der neue Knoten soll mittels InsertNode(newNode, tree) in den Baum eingefügt werden (wie beim nicht-rekursiven Algorithmus).

♣ If der Baum noch leer ist (tree=NIL), then wird der neue Knoten zur Wurzel (tree:=x), (fertig!), else Vergleich der Elemente: if Knotenelement < tree-Element then Einbau des Knotens in den l inken Teilbaum, also Aufruf von InsertNode(x, tree^.L).Achtung: Die Variable tree bekommt in diesem Aufruf den Zeigerwert von tree^.L zu-gewiesen!, d.h. der Zeiger tree zeigt im rekursiven Algorithmus immer auf die Tei lbaumwurzel!Falls Knotenelement nicht kleiner tree-Element (else-Zweig), wir der Knoten in dessen rechten Teilbaum eingebaut, also Aufruf von InsertNode(x, tree^.R).

♣ Ist die richtige Position des Knotens gefunden, wird sein parent-Zeiger auf die letzte(!) Teilbaum-Wurzel (das ist ja sein parent exakt im letzten(!) Aufruf von InsertNode) gesetzt: x^parent := tree.

♣ Der rekursive Algorithmus ist bedeutend eleganter als der nicht-rekursive.

Baum leer → Knoten x ist Wurzel

Einbau von x in linken Teilbaum von tree

PROCEDURE InsertNode(x : LINK; VAR tree : LINK);

BEGIN IF tree = NIL THEN (* leerer (Teil­) Baum *) tree := x

ELSE IF (x^.elem < tree^.elem) THEN

InsertNode(x, tree^.L) (*in linken Teilbaum *) ELSE

InsertNode(x, tree^.R) (*in rechten Teilbaum *) END;

IF (x^.parent = x) THEN x^.parent := tree

END END

END InsertNode;

Einbau von x in rechten Teilbaum von tree

Der parent-Zeiger des Knotens x wird mit der Adresse des Vorgängers belegt.

tree zeigt im rekursiven Algorithmus nicht immer auf die (Gesamt-)Baumwurzelsondern auf die Teilbaumwurzel, in die der neue Knoten x eingebaut werden soll.tree verändert sich bei jedem rekursiven Aufruf.Ist die richtige Stelle für den neuen Knoten x im Baum gefunden, zeigt tree genauauf den Vorgänger (parent)

Page 28: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

28

25

8 32

5 13 26 38

2 6 11 19 30 36 41

31

Ø Beispiel:

Folge: 25 8 32 5 2 6 13 11 19 26 30 31 38 36 41

2

Ø Beispiel: Dieselben Elemente, diesmal der Größe nach geordnet

5

6

8

11

13

19

25

26

30

31

32

36

38

41

Folge: 2 5 6 8 11 13 19 25 26 30 31 32 36 38 41

Page 29: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

29

Ø iterativer Algorithmusgegeben: Zeiger x auf zu löschenden Knoten und Zeiger tree auf Baum(wurzel)Es treten 3 Fälle auf:

0 der Knoten besitzt keine Nachfolger: x^.L=NIL und x^.R=NILIn diesem Fall wird der Vorgänger (parent) des Knotens modifiziert.

1 der Knoten besitzt einen Nachfolger: entweder x^.L=NIL oder x^.R=NILIn diesem Fall wird der Knoten herausgeschnitten (siehe Listen).

2 der Knoten besitzt zwei Nachfolger: weder x^.L=NIL noch x^.R=NILIn diesem Fall wird im rechten Teilbaum des Knotens immer l inks hinuntergegangen bis zum Knoten, der links ein Blatt hängen hat. Dieser Knoten hat folgende Eigenschaften:

♠ Sein Element ist größer als das Element des zu löschenden Knotens und alle Knotenelemente im linken Teilbaum des zu löschenden Knotens

♠ Sein Element ist das kleinste im rechten Teilbaum des zu löschenden Knotens♠ Sein Element folgt also in der Elementordnung dem Element des zu löschenden Knotens♠ Der Knoten besitzt höchstens einen Nachfolger

Dieser Knoten wird wie im Fall (0) oder (1) herausgeschnitten und an die Stelle des zu löschenden Knotens gesetzt.

Löschen eines Knotens

5

6

5

löschen

5

6

10

5

10löschen

keine Nachfolger: ein Nachfolger:

zwei Nachfolger: 32

26

24

28

22 25

35

32 40

29

löschen

ausschneiden

32

28

24

22 25

35

32 40

29

Page 30: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

30

Ersetze Knoten old durch Knoten new

PROCEDURE ReplaceNode(old, new : LINK);

BEGIN old^.elem := new^.elem; new^.parent := new; new^.L := NIL; new^.R := NIL END ReplaceNode;

PROCEDURE SuccessorElem(x : LINK) : LINK;

BEGIN x := x^.R; IF (x <> NIL) THEN WHILE (x^.L <> NIL) DO x := x^.L

END END; RETURN x END SuccessorElem;

Ø Programm; zuerst zwei Hilfsprozeduren

Überschreibe altes Knotenelement mit neuem

Die Zeiger des neuen Knotens werden „ausgehängt“

Finde den Knoten mit dem nächstgrösseren Element

x zeigt auf den Knoten, für den der Knoten mit dem nächstgrößere Element gesucht werden soll .Ein Schritt nach rechts, dann solange Schritte nach l inks, bis der Zeiger x auf einen Knoten mit l inkem Blatt zeigt. Dieser Knoten enthält das nächstgrößere Element

Lösche Knoten xØ Programm; jetzt die Lösch-Prozedur (1. Teil)

Fall 0 oder 1: der Knoten x wird mit Zeiger del markiert, der Unterbaum von x wird an seiner Wurzel mit Zeiger subT markiert.

Fall 2: der Knoten mit dem nächstgrößeren Element wird mit Zeiger del markiert, des Knotens Unterbaum wird an seiner Wurzel mit Zeiger subT markiert.

PROCEDURE DeleteNode(x : LINK; VAR tree : LINK);

VAR del, subT : LINK;

BEGIN IF (x^.L = NIL) OR (x^.R = NIL) THEN del := x; IF (x^.L = NIL) THEN subT := x^.R

ELSE subT := x^.L END

ELSE del := SuccessorElem(x);subT := del^.R

END;

...

Page 31: Teil III : Bäume - mathematik.uni-ulm.de · 3 REPEAT pop UNTIL (: alle Operatoren auf dem stack bis zur öffnenden Klammer → in Ausgabestring; dann werden beide Klammern gelöscht

31

...

IF (x^.parent = x) THEN (* x = root(tree) ? *) tree := subT; IF (subT <> NIL) THEN subT^.parent := subT

END ELSE IF (del^.parent^.L = del) THEN del^.parent^.L := subT

ELSE del^.parent^.R := subT END; IF (subT <> NIL) THEN subT^.parent := del^.parent

END; IF (del <> x) THEN (* x­Knoten ersetzen ? *) replaceNode(x, del)

END END; DISPOSE(del) END DeleteNode;

Ø Programm; die Lösch-Prozedur (cont‘d)

Löschen von del (Fall 0,1,2): falls del am linken(rechten) Zeiger seines parent hing, wird dort jetzt subT angehängt

del <> x gibt es nur im Fall 2: dort wird der Knoten mit dem nächstgrößeren Element gelöscht und dessen Element im Knoten x eingesetzt. (gleichbedeutend mit Löschen von x und ersetzen durch Knoten mit dem nächstgrößeren Element.

Falls die (Gesamt-)Baumwurzel gelöscht werden soll, dann wird der Baumwurzelzeiger tree umgesetzt auf den Knoten, auf den subT zeigt und eine neue Wurzel gebildet.

§ Ein Baum ist rekursiv definiert: An seiner Wurzel hängen (Teil-)bäume. Er besteht aus Knoten und Kanten. Jeder Knoten hat einen parent und 0 ... mehrere children. Anwendungen sind: übersichtl iche Darstellung, effiziente Suche, ...

§ Arithmetische Ausdrücke werden gewöhnlich in infix-Notation geschrieben oder als

Termbaum gezeichnet. Für die maschinelle Verarbeitung ist die (klammerlose)

postfix-Notation geeignet. Eine Transformation infix- → postfix-Notation ist mittels shunting-yard-algorithm möglich. Die Generierung eines Termbaums im Rechner geschieht mittels „Verzeigerung“ von Knoten-Records, die ein Element besitzen, eine Adresse (auf die ein Zeiger eines anderen Knoten-Records zeigen kann) und drei eigene Zeiger (parent, left child, right child) zum „Verzeigern“ mit anderen Knoten (Kanten)

§ Traversieren von Bäumen: Durchlaufen eines gegebenen Baumes entlang der Kan-ten, wobei jeder Knoten einmal besucht wird, um dort eine Operation durchzuführen (auslesen, einlesen, vergleichen, markieren, ...). 4 Verfahren zur Traversierungwurden vorgestellt: pre-order, in-order, post-order, level-order

§ Suchbäume sind aufgebaut aus Knoten mit Elementen (die sich ordnen lassen).

Einbau eines zusätzlichen Knotens: Dieser wird „über die Baumwurzel eingespeist“ und je nachdem ob sein Element kleiner/größer ist als das Wurzelelement, steigt der Knoten einen Links-/Rechtsschritt den Baum hinab, usw. Dies geschieht bis zu einem „leeren Ende“. Dort wird der Knoten „eingehängt“.Weitere Standard- Operationen: Löschen eines Knotens, Suchen etc .