SS17 Algorithmen und Datenstrukturen 3. Kapitel Binärbäume Martin Dietzfelbinger April 2017 FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 3.1 Binärbäume: Grundlagen Der Datentyp (und die Datenstruktur) Binärbaum tritt überall in der Informatik auf: • als binärer Suchbaum • als Repräsentation von binären Ausdrücken (logisch, arithmetisch) • als Entscheidungsbaum • als Codierungs-/Decodierungsbaum • als binärer Heap (später) • ... FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 1 Beispiel 1: Arithmetischer Ausdruck mit zweistelligen Operatoren: ((((x2 · x4) + ((x3 − x7) − (x6/x1))) + (x5 · (x9 · x3))) / ((x5 − x6) − x1)) FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 2 / − + − x2 x4 FG KTuEA, TU Ilmenau x9 / x7 x5 x5 − x3 x1 − + x6 x6 x3 x1 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 3 Auswertung: 1) Ordne den Blättern konkrete Werte zu, z.B. x1 = 5, x2 = 3, x3 = −2, x4 = −7, x5 = 7, x6 = 10, x7 = 5, x9 = −5. 2) Werte aus, von den Blättern startend ( bottom-up“). ” / −5 40 + − −30 + 3 −9 −7 − −7 FG KTuEA, TU Ilmenau 7 2 5 − 10 − −2 −3 70 −21 10 / −5 −8 7 5 10 −2 5 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 4 Beispiel 2: Codierungs-/Decodierungsbaum Zeichen aus Alphabet Σ erhalten binäre Codes. Diese können auch verschiedene Länge haben: Wenige Bits für häufige Buchstaben, viele Bits für seltene.“ ” Mini-Beispiel: A 1100 B 0110 C 000 D 111 E 10 F 0011 G 010 H 0010 I 0111 K 1101 Zur Codierung von Zeichenreihen benutzt man direkt die Tabelle. Beispiel: FEIGE hat Codierung 0011 10 0111 010 10. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 5 Präfixfreier“ Code: Kein Codewort ist Anfangsstück eines ” anderen. Damit: eindeutig decodierbar“; ” Fuge zwischen Codes für Buchstaben muss nicht markiert werden: Schreibe 001110011101010 statt 0011 10 0111 010 10. Kompakte Repräsentation des Codes als Binärbaum: 0 0 0 C FG KTuEA, TU Ilmenau 1 1 0 H 1 1 F 0 G 0 E 0 1 0 B 1 1 I 0 A Algorithmen und Datenstrukturen – SS17 – Kapitel 3 1 D 1 K 6 0 0 0 C 1 1 0 H 1 1 F 0 G 0 E 0 1 0 B 1 1 I 0 A 1 D 1 K Blätter sind mit Buchstaben markiert; Weg von der Wurzel zum Blatt gibt das Codewort wieder (links: 0, rechts: 1). Decodierung: Laufe Weg im Baum, vom Codewort gesteuert, bis zum Blatt. Wegen Präfixeigenschaft: im Code keine Zwischenräume nötig. Beispiel: 0000010100011 liefert CHEF“. ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 7 Binärbaum-Terminologie: Überblick Wurzel linkes Kind von v2 v1 Kante/Zeiger v2 Vater von v5 v6 v3 v4 v7 v10 l8 l4 v 8 l0 l1 l7 l2 l5 FG KTuEA, TU Ilmenau rechtes Kind von v5 v9 l3 v9 l9 l10 Blatt, externer/äußerer Knoten l6 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 8 Mathematische Struktur: flach“ ” Definition 3.1.1 Ein Binärbaum T besteht aus einer endlichen Menge V von inneren“ Knoten, einer dazu disjunkten endlichen Menge L ” von äußeren“ Knoten sowie einer injektiven Funktion ” child : V × {left, right} → V ∪ L, wobei Folgendes gilt: (i) In V ∪ L gibt es genau einen Knoten r, der nicht als Wert child(v, left ) oder child(v, right ) vorkommt. Dieser Knoten r heißt die Wurzel. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 9 Mathematische Struktur: flach“ (Forts.) ” child(v, left ) [child(v, right )] heißt das linke [rechte] Kind von v ∈ V . Weil child injektiv ist, gibt es für jeden Knoten w ∈ (V ∪ L) mit w 6= r genau einen Knoten u ∈ V mit w = child(u, left) oder w = child(u, right) (aber nicht beides). Dieser Knoten u wird mit p(w) bezeichnet und heißt der Vorgängerknoten oder Vaterknoten von w. Wir sagen: Von p(w) nach w verläuft eine Kante. w heißt [linkes bzw. rechtes] Kind von p(w). FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 10 Mathematische Struktur: flach“ (Forts.) ” Die folgende Struktur erfüllt (i), ist aber kein Binärbaum: (ii) Kreisfreiheit“: Für jeden Knoten w ∈ V ∪ L gilt: ” Die Folge v0 = w, v1 = p(w), v2 = p(v1), v3 = p(v2), . . . bricht nach endlich vielen Schritten mit einem vd = r ab. (Dadurch ist ein eindeutiger Weg von w zur Wurzel festgelegt. Jeder Knoten des Binärbaums ist von der Wurzel aus erreichbar.) FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 11 Mathematische Struktur: flach“ (Forts.) ” Knoten und Kanten können Markierungen (oder Beschriftungen) tragen, die auch als Funktionen dargestellt werden. Knotenmarkierungen: (D, Z sind beliebige Mengen.) Funktionen mV : V → D und mL : L → Z. Kantenmarkierungen: (X ist beliebige Menge.) Funktion mK : V × {left, right} → X . Beispiel: In einem Codierungsbaum sind die Blätter mit Buchstaben markiert, die beiden Kanten, die aus einem inneren Knoten herausführen, mit 0 und 1. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 12 Mathematische Struktur: rekursiv D: Menge von Knotenmarkierungen Z: Menge von Blattmarkierungen (Induktive) Definition 3.1.2 (i) Wenn z ∈ Z, dann ist (z) ein (D, Z)-Binärbaum. // Blatt mit Markierung z. Auch: z (ohne Klammern), z (ii) Wenn T1, T2 (D, Z)-Binärbäume sind und x ∈ D ist, dann ist auch (T1, x, T2) ein (D, Z)-Binärbaum. // Wurzel mit Markierung x, linker Unterbaum T1, rechter Unterbaum T2. (iii)∗ Nichts sonst ist (D, Z)-Binärbaum. ∗ (iii) wird bei induktiven Definitionen meist weggelassen. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 13 Beispiel: D = {a, . . . , z} und Z = N. – Tupeldarstellung: (((37, b, (17, a, 31)), c, 7), b, ((29, d, (1, r, 23)), z, (13, u, 3))) Graphische Darstellung: b c 7 b 37 d u 29 a 17 FG KTuEA, TU Ilmenau z 31 13 r 1 3 23 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 14 Beispiel: Arithmetischer Ausdruck als Baum D = {+, −, ·, /} und Z = {x1, x2, x3, . . .}. / − + − x2 x4 x9 / x7 x5 x5 − x3 x1 − + x6 x6 x3 x1 ((((x2 · x4) + ((x3 − x7) − (x6/x1))) + (x5 · (x9 · x3)))/((x5 − x6) − x1)) Der Ausdruck ist genau die Tupeldarstellung ohne Kommas! FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 15 Mathematische Struktur: rekursiv (Forts.) (((37, b, (17, a, 31)), c, 7), b, ((29, d, (1, r, 23)), z, (13, u, 3))) Beachte: Man kann die rekursiv definierten Binärbäume auf zwei (letztendlich äquivalente) Arten auffassen: (a) als geschachtelte Tripel oder (b) als Zeichenreihen mit Symbolen aus D ∪ Z ∪ {(, ), “,”}. Auffassung (a) ist mathematisch klarer, da aus gegebenem T = (T1, x, T2) die Komponenten T1, x und T2 unmittelbar abgelesen werden können (ohne Syntaxanalyse o. ä.). Vorteil der rekursiven Auffassung: Übersichtlichere (rekursive) Programme und Korrektheitsüberlegungen. Vorteil der flachen“ Auffassung: ” Eventuell effizientere Ausführung (Schleifen statt rekursive Prozeduraufrufe). FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 16 (((37, b, (17, a, 31)), c, 7), b, ((29, d, (1, r, 23)), z, (13, u, 3))) (Rekursiver) Umbau von rekursiver zu flacher“ Struktur: ” Sei T ein (D, Z)-Binärbaum. Wenn T = z = (z) für ein z ∈ Z, dann ist die flache“ ” Version von T ein äußerer Knoten mit Inschrift z. Dieser ist auch die Wurzel. Wenn T = (T1, x, T2), dann werden rekursiv flache“ Versio” nen der beiden Unterbäume T1 und T2 hergestellt, mit Wurzeln r1 und r2 und disjunkten Knotenmengen V1, V2, L1, L2. V := V1 ∪ V2; L := L1 ∪ L2; child := child1 ∪ child2. Schließlich wird ein neuer innerer Knoten r mit Inschrift x erzeugt und zusätzlich child(r, left) = r1 und child(r, right) = r2 gesetzt. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 17 Baum, rekursiv, als Text → flache“ Struktur ” Umbau von rekursiver Struktur (Text) zu flacher“ Struktur: ” Prozedur TreeText2Flat() Verfahren: Liest (D, Z)-Binärbaum (als Textstrom) von links nach rechts, baut T ( flach“) mit Wurzel v. ” lies (“; // lies“ heißt: Zeichen wird verbraucht ” ” wenn nächstes Zeichen z ∈ Z ist: lies z; T ← z ; dies ist Wurzel von T ; sonst: baue leere Wurzel v für T ; T1 ← TreeText2Flat(); child(v, left) ← Wurzel v1 von T1; lies ,“; ” lies Element x ∈ D; data(v) ← x; lies ,“; ” T2 ← TreeText2Flat(); child(v, right) ← Wurzel v2 von T2; lies )“. ” return T , mit Wurzel v. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 18 Umbau von flacher“ zu rekursiver Struktur: ” Gegeben: Baum T mit Knotenbeschriftungen als V , L, child, mV : V → D und mL : L → Z. Baue rekursiv für jeden Knoten v ∈ V ∪ L einen Baum Tv . Prozedur Flat2Tree(v) arbeitet folgendermaßen (die Beschreibung von T ist global gegeben): Falls v ∈ L ein Blatt mit mL(v) = z ist: return Tv = (z). Falls v ∈ V ein innerer Knoten mit mV (v) = x ist: T1 ← Flat2Tree(child(v, left)); T2 ← Flat2Tree(child(v, right)); return Tv = (T1, x, T2). Um T zu transformieren: Flat2Tree(r) für Wurzel r von T . FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 19 Spezifikation des Datentyps Binärbaum“ ” Datentyp Binärbaum über D: (leere äußere Knoten) 1. Signatur: Sorten: Elements Bintrees Boolean Operationen: empty : → Bintrees buildTree: Elements × Bintrees × Bintrees → Bintrees leftSubtree: Bintrees → Bintrees rightSubtree: Bintrees → Bintrees data: Bintrees → Elements isempty : Bintrees → Boolean 2. Mathematisches Modell: FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 20 Sorten: Elements: Bintrees: Boolean: (nichtleere) Menge D {T | T ist (D, {−})-Binärbaum} {true, false} Op’en: empty = (−) =: // leerer Baum“ ” buildTree(x, T1, T2) := (T1, x, T2) T1, falls T = (T1, x, T2) leftSubtree(T ) := undefiniert, falls T = T2, falls T = (T1, x, T2) rightSubtree(T ) := undefiniert, falls T = x, falls T = (T1, x, T2) data(T ) := undefiniert, falls T = false, falls T = (T1, x, T2) isempty (T ) := true, falls T = FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 21 Binärbäume, Implementierung I: Zeigerstruktur bzw. Referenzstruktur, vgl. AuP-Vorlesung. Mit markierten externen Knoten. T: b z c b a 37 17 FG KTuEA, TU Ilmenau d 7 u r 29 31 1 13 3 23 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 22 Binärbäume, Implementierung II: Leere externe Knoten T: b z c d b a u r Externe Knoten werden nicht repräsentiert (null-Zeiger/Referenz). Oder: 1 externer Knoten `, Referenz auf ` statt null. Speicherplatzbedarf für n Knoten: n Dateneinträge, 2n Zeiger/Referenzen, davon n+1 mal null. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 23 Mögliche Erweiterung: Vaterzeiger. T: Wurzel b z c d b a u r Erleichtert Navigieren im Baum, besonders bei Verwenden der flachen“ Auffassung und von iterativen Verfahren. ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 24 Implementierung der Operationen des mathematischen Modells: Baum wird immer als Zeiger bzw. Referenz auf den Wurzelknoten dargestellt. empty, isempty, data: klar. leftSubtree, rightSubtree: Zeiger/Referenz zurückgeben. buildTree(x, T1, T2) erzeugt einen neuen Knoten (Wurzel) r mit Eintrag x, die Wurzeln von T1 bzw. T2 werden linkes bzw. rechtes Kind von r. Der Benutzer der buildTree-Operation muss sicherstellen, dass die Knotenmengen von T1 und T2 disjunkt sind! FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 25 3.2 Binärbäume: Terminologie • Binärbaum, engl: binary tree“ ” • (innerer) Knoten v, engl: node“ ” • Knoteneintrag: x = data(v) = data(T 0) (T 0 = Tv ) x v FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 26 • Tv : Unterbaum mit Wurzel v x v Tv Der Teil von T , der aus den Knoten besteht, deren Weg zur Wurzel durch v verläuft. Die Wurzel ist v. Dabei kann v ein beliebiger innerer oder äußerer Knoten sein. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 27 • (äußerer) Knoten ≡ Blatt l, engl: leaf “, Plural leaves“ ” ” • Wurzel, engl: root“ ” z l • Blatteintrag: z = data(l) FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 28 • Vater ≡ (unmittelbarer) Vorgänger, engl: parent“, von v: p(v) ” • linkes Kind ≡ (unmittelbarer) Nachfolger, Sohn, engl: left child“, von v: child(v, left) ” • rechtes Kind ≡ (unmittelbarer) Nachfolger, Sohn, engl: right child“, von v: child(v, right) ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 29 • Vorfahr (Vater von Vater von Vater . . . von v), engl: ancestor“ (Im Bild: v ist Vorfahr von u.) ” • Nachfahr (Kind von Kind von . . . von v), engl: descendant“ (Im Bild: u ist Nachfahr von v.) ” v u Achtung: Oft gilt v als (uneigentlicher) Vorfahr/Nachfahr von v. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 30 • Weg in T : Knotenfolge oder Kantenfolge, die von v zu einem Nachfahren u führt • Länge eines Wegs (v0, v1, . . . , vs): Anzahl s der Kanten auf dem Weg v Weg der Länge 3 von v nach u u FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 31 Häufiger Spezialfall: Die externen Knoten haben keinen Eintrag. (Bzw. jeder hat denselben nichtssagenden Eintrag, z.B. −“ .) ” Ein solcher externer Knoten wird auch als leerer Baum“ ” bezeichnet. "Blätter" Oft bezeichnet man dann die inneren Knoten, die keinen inneren Knoten als Nachfolger haben, als Blätter“. ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 32 Tiefe/Level eines Knotens Die Länge (das ist die Kantenzahl) des Wegs (v0, v1, . . . , vd) von der Wurzel r = v0 zum Knoten v = vd heißt die Tiefe oder das Level d(v) von Knoten v. Auch externen Knoten wird so eine Tiefe zugeordnet. 0 1 2 d ( v )=3 v 3 4 FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 33 Tiefe/Höhe eines Binärbaums Die Tiefe oder Höhe d(T ) (auch: h(T )) eines Binärbaums T ist definiert wie folgt: 1. Fall: Die externen Knoten sind leer (): d(T ) = max({−1} ∪ {d(v) | v innerer Knoten in T }). Beobachte induktive Formel: d(T ) = −1 für T = und d((T1, x, T2)) = 1 + max{d(T1), d(T2)}. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 34 Beispiele: Tiefen/Höhen von Binärbäumen mit leeren externen Knoten. Höhe −1 Höhe 0 Höhe 3: x5 x2 T1 x6 x1 x4 T2 x7 x3 FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 35 Tiefe/Höhe eines Binärbaums Definition der Tiefe/Höhe von T : 2. Fall: Die externen Knoten sind nicht leer ((z), z ∈ Z): d(T ) := max{d(v) | v äußerer Knoten in T }. 0 0 0 C 1 1 0 H 1 1 F 0 G 0 E 0 1 0 B 1 1 I 0 A 1 D 1 K Tiefe 4, gleich der maximalen Länge eines Weges zu einem Blatt. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 36 Definition der Höhe eines Knotens: Die Höhe h(v) eines Knotens in T ist definiert als die Tiefe d(Tv ) des Teilbaums mit Wurzel v. – Beispiel: Höhe: 5 Höhe: 4 Höhe: 2 Höhe: 1 Höhe: 0 Hier angegeben: Fall Blätter nicht leer“. ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 37 3.3 Binärbäume: Eigenschaften Proposition 3.3.1 Es sei T ein Binärbaum mit n ≥ 0 inneren Knoten und leeren äußeren Knoten. Dann gilt: (a) (b) T hat 2n Zeiger/Kanten. (Beispiel: n = 10, 2n = 20) T hat n + 1 äußere Knoten. (Beispiel: n + 1 = 11) FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 38 (c) Auf Level l liegen höchstens 2l Knoten, l = 0, 1, 2, . . .. (d) Auf Level 0, 1, . . . , l zusammen liegen höchstens 1 + 2 + 4 + · · · + 2l = 2l+1 − 1 innere Knoten. Daraus: log(n + 1) ≤ l + 1, für das Level l mit dem tiefsten inneren Knoten. (e) n − 1 ≥ d(T ) ≥ dlog(n + 1)e − 1. Merke: Die Tiefe eines Binärbaums mit n inneren Knoten ist mindestens log n − 1. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 39 Beweis von 3.3.1: (a) Jeder innere Knoten hat zwei Zeiger/Kanten zu Kindern. (b) Jeder Knoten außer der Wurzel hat eine eingehende Kante. Nach (a) gibt es 2n Kanten, und es gibt n − 1 innere Knoten, die nicht die Wurzel sind. Daher muss es 2n − (n − 1) = n + 1 äußere Knoten geben. (c) Beweis durch Induktion über l. l = 0: Nur die Wurzel hat Level 0, und 20 = 1. l − 1 → l“: Nach I.V. liegen auf Level l − 1 höchstens 2l−1 Knoten. ” Jeder davon hat höchstens zwei Kinder. Also liegen auf Level l höchstens 2l−1 · 2 = 2l Knoten. (d) Sei l das maximale Level, das einen inneren Knoten enthält. Alle Levels bis l zusammen enthalten n Knoten; nach (c) ist n ≤ 20 + 21 + · · · + 2l. l+1 Die Schranke n ≤ 2 − 1 folgt dann mit Hilfe der Summenformel P l k q = (q − 1)/(q − 1) für geometrische Reihen. 0≤l<k Dann folgt n + 1 ≤ 2l+1, also durch Logarithmieren: log(n + 1) ≤ l + 1. (e) In der Situation von (d) gilt l ≥ log(n + 1) − 1; weil l ganzzahlig ist, folgt l ≥ dlog(n + 1)e − 1. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 40 Proposition 3.3.2 Es sei T ein Binärbaum mit N ≥ 1 nichtleeren äußeren Knoten. Dann gilt: (a) T hat n = N − 1 innere Knoten. (Bsp.: N = 11, n = 10) (b) T hat 2N − 2 Zeiger/Kanten. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 41 (c) N ≤ 2d(T ). (Beweis: Induktion über Binärbaume, rekursive Struktur.) (d) N − 1 ≥ d(T ) ≥ dlog N e. Merke: Die Tiefe eines Binärbaums mit N nichtleeren äußeren Knoten ist mindestens log N . FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 42 Beweis von 3.3.2: (a) Dies ist nur eine Umformulierung von Prop. 3.3.1(b). (b) Dies ist eine Umformulierung von Prop. 3.3.1(a). (c) Durch (verallgemeinerte) Induktion über d(T ) zeigen wir, dass die Anzahl NT der Blätter von T nicht größer als 2d(T ) ist. I.A.: d(T ) = 0: NT = 1 und 20 = 1. I.Schritt: Sei d(T ) > 0. Dann hat T eine Wurzel, die innerer Knoten ist, und zwei Unterbäume T1 und T2 mit max{d(T1), d(T2)} = d(T ) − 1. Baum T hat NT = NT1 + NT2 Blätter. Nach I.V. gilt NTi ≤ 2d(Ti), also NTi ≤ 2d(T )−1, für i = 1, 2. Also: NT = NT1 + NT2 ≤ 2 · 2d(T )−1 = 2d(T ). (d) Ergebnis (c) bedeutet NT ≤ 2d(T ). Logarithmieren liefert log(NT ) ≤ d(T ). FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 43 Totale innere Weglänge Wieviele Kanten durchlaufe ich insgesamt, wenn ich zu jedem inneren Knoten einmal hinlaufe? 0 + 2 · 1 + 3 · 2 + 3 · 3 + 1 · 4 = 21 Totale innere Weglänge ( total internal path length“): ” P TIPL(T ) := v∈V d(v). (Im Beispiel: 21.) Mittlere innere Weglänge: FG KTuEA, TU Ilmenau 1 n · TIPL(T ). (Im Beispiel Algorithmen und Datenstrukturen – SS17 – Kapitel 3 21 10 .) 44 Totale äußere Weglänge Wieviele Kanten durchlaufe ich insgesamt, wenn ich zu jedem äußeren Knoten einmal hinlaufe? 2 + 3 · 3 + 5 · 4 + 2 · 5 = 41. Totale äußere Weglänge ( total external path length“): ” P TEPL(T ) := l∈L d(l). (Im Beispiel: 41.) Mittlere äußere Weglänge: TEPL(T )/(n + 1). (Im Beispiel 41 11 .) FG KTuEA, TU Ilmenau 45 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 Proposition 3.3.3 Für jeden Binärbaum mit n inneren Knoten gilt: TEPL(T ) = TIPL(T ) + 2n. Beweis: Induktion über die Knotenanzahl von Binärbäumen. ( z ): z I.A.: n = 0: TEPL(T ) = 0 (ein Weg der Länge 0) und TIPL(T ) = 0 (leere Summe, da kein innerer Knoten). FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 46 I.V.: n > 0, Beh. richtig für alle T 0 mit n0 < n inneren Knoten. D. h.: TEPL(T 0) − TIPL(T 0) = 2n0. I.S.: T = ( T ,x,T ): 1 2 x T1 T2 n1 = Anzahl innerer Knoten in T1; n2 = Anzahl innerer Knoten in T2. Klar: n = 1 + n1 + n2. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 47 Die n1 + 1 bzw. n2 + 1 externen Knoten in den Teilbäumen hängen in T ein Level tiefer: TEPL(T ) = (TEPL(T1) + (n1 + 1)) + (TEPL(T2) + (n2 + 1)). Auch die n1 bzw. n2 internen Knoten in den Teilbäumen hängen in T ein Level tiefer: TIPL(T ) = 0 +(TIPL(T1) + n1) + (TIPL(T2) + n2). |{z} Wurzel Subtraktion liefert: TEPL(T ) − TIPL(T ) = I.V. = (TEPL(T1) − TIPL(T1)) + (TEPL(T2) − TIPL(T2)) + 2 2n1 + 2n2 + 2 = 2n. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 48 Nächstes Ziel: Auch die mittlere Weglänge in Binärbäumen wächst mindestens logarithmisch mit der Knotenanzahl. . 1 4 1 + 3 · 18 + 6 · 16 =1 Lemma 3.3.4 Es sei L die Menge der äußeren Knoten in einem Binärbaum T . X Dann gilt: 2−d(l) = 1. l∈L FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 49 Nächstes Ziel: Auch die mittlere Weglänge in Binärbäumen wächst mindestens logarithmisch mit der Knotenanzahl. . 1 4 1/4 1/8 1/8 1/8 1/16 1/16 1 + 3 · 18 + 6 · 16 =1 1/16 1/16 1/16 1/16 Lemma 3.3.4 Es sei L die Menge der äußeren Knoten in einem Binärbaum T . X Dann gilt: 2−d(l) = 1. l∈L FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 49 Beweis: Wie in einem Kodierungsbaum markiere in jedem inneren Knoten die Kante zum linken Kind mit 0, die zum rechten Kind mit 1. Jedem Blatt l entspricht dann eine Bitfolge wl = b1 · · · bd(l). Sei D = d(T ) die Tiefe des tiefsten Blatts. Jedes wl kann man auf 2D−d(l) Arten zu einer Bitfolge der Länge D verlängern. Alle so erzeugten Bitfolgen sind verschieden; alle 2D Bitfolgen werden so erzeugt. X ⇒ 2D−d(l) = 2D . l∈L ⇒ Behauptung. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 50 Proposition 3.3.5 T hat N = n + 1 äußere Knoten ⇒ TEPL(T ) ≥ N log N . Beweis: Die Logarithmusfunktion ist konkav : log((1 − λ)a + λb)) ≥ (1 − λ) log a + λ log b, für 0 ≤ λ ≤ 1. Daraus: 1 log( M P 1≤i≤M ai) ≥ 1 M P 1≤i≤M log(ai). Anwenden auf M = N = n + 1 und al = 2−d(l), l ∈ L: P P 1 1 −d(l) log( N l∈L 2 ) ≥ N l∈L(−d(l)). X P 2−d(l) D.h.: TEPL(T ) = l∈L d(l) ≥ −N log N1 |l∈L {z =1 Der letzte Term ist = −N log( N1 ) = N log N . FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 } 51 Folgerung: Für die mittlere äußere Weglänge eines Binärbaums T mit N Blättern gilt: 1 TEPL(T ) ≥ log N. N Nach Proposition 3.3.3: TEPL(T ) = TIPL(T ) + 2n Also: TIPL(T ) ≥ TEPL(T ) − 2n ≥ (n + 1) log(n + 1) − 2n > n(log n − 2). Folgerung: Für die mittlere innere Weglänge eines Binärbaums T mit n Knoten gilt: 1 TIPL(T ) > log n − 2. n FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 52 3.4 Durchläufe durch Binärbäume (D, Z)-Binärbäume kann man systematisch durchlaufen, die Knoten nacheinander besuchen und (anwendungsabhängige) Aktionen an den Knoten ausführen. Abstrakt gefasst: visit-Operation: organisiere data-Teil der Knoten als Objekte einer Klasse; visit(T ) löst Abarbeitung einer Methode von data(T ) aus. Möglichkeiten für visit bei Knoten v: – Daten data(v) ausgeben; – laufende Nummer für v vergeben; – Zeiger auf v an Liste anhängen; – zu v gehörende Aktion ausführen (z. B. arithmetische Operation durchführen) usw. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 53 Inorder-Durchlauf durch T falls T = (z): e-visit(z) ; // besuche äußeren Knoten falls T = (T1, x, T2): Inorder-Durchlauf durch T1; i-visit(x) ; // besuche inneren Knoten Inorder-Durchlauf durch T2. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 54 Inorder-Durchlauf durch T b 1 0 0 1 c z 1 0 0 1 11 00 00 11 7 1 0 0 1 b 1 0 37 11 00 00 11 a 11 00 00 11 17 31 1 0 11 0 00 1 d u 1 0 29 11 00 11 00 r 11 00 00 11 1 13 11 00 00 11 3 1 0 0 1 23 11 00 00 00 11 11 00 11 Ausgabe: 37, b, 17, a, 31, c, 7, b, 29, d, 1, r, 23, z, 13, u, 3. Beobachte: Abwechselnd externe und interne Knoten. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 55 Präorder-Durchlauf durch T falls T = (z): e-visit(z) ; falls T = (T1, x, T2): i-visit(x) ; Präorder-Durchlauf durch T1; Präorder-Durchlauf durch T2; FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 56 Präorder-Durchlauf durch T 1 0 0b 1 1 0 1 0 0z 1 c 11 00 00b 11 37 11 00 00 11 1 0 0 1 1a 0 17 11 00 31 FG KTuEA, TU Ilmenau 00 u 11 d 29 1 0 11 0 00 1 Ausgabe: 1 0 7 1r 0 1 13 11 00 00 11 3 1 0 0 1 23 11 00 00 00 11 11 00 11 b, c, b, 37, a, 17, 31, 7, z, d, 29, r, 1, 23, u, 13, 3 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 57 Postorder-Durchlauf durch T falls T = (z): e-visit(z) ; falls T = (T1, x, T2): Postorder-Durchlauf durch T1; Postorder-Durchlauf durch T2; i-visit(x) ; FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 58 Postorder-Durchlauf durch T b c 00 11 b11 00 37 11 00 00 11 17 1 0 FG KTuEA, TU Ilmenau z 1 0 0 1 1 0 31 1 0 11 0 00 1 Ausgabe: 11 00 7 a 1 0 0 1 d 1 0 0 1 u 11 00 r 29 11 00 1 13 11 00 00 11 1 0 3 1 0 0 1 23 11 00 00 00 11 11 00 11 37, 17, 31, a, b, 7, c, 29, 1, 23, r, d, 13, 3, u, z, b. Algorithmen und Datenstrukturen – SS17 – Kapitel 3 59 Beispiel: Arithmetischer Ausdruck als Baum D = {+, −, ·, /} und Z = {x1, x2, x3, . . .}. / − + − x2 x4 x9 / x7 x5 x5 − x3 x1 − + x6 x6 x3 x1 Ordne den Blättern konkrete Werte zu, z.B. x1 = 5, x2 = 3, x3 = −2, x4 = −7, x5 = 7, x6 = 10, x7 = 5, x9 = −5. Auswertungsprozedur ordnet jedem Knoten einen Wert zu. Geeignete Reihenfolge: Postorder-Durchlauf. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 60 Beispiel: Arithmetischer Ausdruck als Baum D = {+, −, ·, /} und Z = {x1, x2, x3, . . .}. / + − + − 3 −2 −5 / 5 7 7 − −7 5 − 10 10 −2 5 Ordne den Blättern konkrete Werte zu, z.B. x1 = 5, x2 = 3, x3 = −2, x4 = −7, x5 = 7, x6 = 10, x7 = 5, x9 = −5. Auswertungsprozedur ordnet jedem Knoten einen Wert zu. Geeignete Reihenfolge: Postorder-Durchlauf. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 61 Beispiel: Arithmetischer Ausdruck als Baum D = {+, −, ·, /} und Z = {x1, x2, x3, . . .}. / 40 + −30 0 5 + 1 0 1 −21 11 00 1 00 11 3 −7 −7 − −2 1 0 8 0 1 −9 11 00 − 4 7 00 11 2 0 1 00 11 / 3 0 1 00 11 2 0 1 00 11 5 10 −5 0 1 1 0 11 0 1 −81 0 0 10 − 1 0 1 70 11 00 00 11 7 00 11 −3 1 0 0 5 − 1 9 0 1 10 1 0 6 0 1 −5 7 10 −2 5 Ordne den Blättern konkrete Werte zu, z.B. x1 = 5, x2 = 3, x3 = −2, x4 = −7, x5 = 7, x6 = 10, x7 = 5, x9 = −5. Auswertungsprozedur ordnet jedem Knoten einen Wert zu. Geeignete Reihenfolge: Postorder-Durchlauf. (Rote Kreise.) FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 61 Auch möglich: Kombi-Durchlauf: falls T = (z): e-visit(z) ; falls T = (T1, x, T2): preord-i-visit(x) ; Kombi-Durchlauf durch T1; inord-i-visit(x) ; Kombi-Durchlauf durch T2; postord-i-visit(x) ; Ermöglicht Datentransport von der Wurzel nach unten in den Baum hinein und wieder zurück. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 62 Kombi-Durchlauf durch T 11 00 00b11 11 00 00 11 1 0 37 11 00 00 11 0 1 c 0 1 0 1 0 1 7 1 0 0 1 29 0a 0 1 1 00 11 00 11 00 11 17 31 1 0 11 0 00 1 FG KTuEA, TU Ilmenau 0 1 1 0 0 0b 1 1 0 1 0 1 1 0 11 000 1 z 00 11 00 11 1 0 0 1 0 d 1 1 0 11 u 00 11 00 11 13 0 00 1 r 00 11 00 11 00 00 11 11 1 1 0 3 1 0 0 1 23 11 00 00 00 11 11 00 11 Algorithmen und Datenstrukturen – SS17 – Kapitel 3 63 Beispiel für Anwendung eines Kombi-Durchlaufs: Generierung einer String-Darstellung eines Binärbaums. Zeichen werden sequenziell in die Ausgabe geschrieben. e-visit(z): Schreibe (z)“. ” preord-i-visit(x): Schreibe (“. ” inord-i-visit(x): Schreibe , x,“. ” postord-i-visit(x): Schreibe )“. ” FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 64 Zeitanalyse für Durchlauf Die Baumdurchläufe können mittels rekursiver Prozeduren implementiert werden. Beispiel: Inorder-Durchlauf. Prozedur: inorder(T) Angewendet auf einen Baum T mit n inneren Knoten. Für jeden inneren und äußeren Knoten wird die Prozedur inorder(.) einmal aufgerufen, insgesamt (2n + 1)-mal. Kosten pro Aufruf: O(1) plus Kosten für i-visit/e-visit-Operation. Insgesamt: (2n + 1) · (O(1) + Cvisit), wo Cvisit eine Schranke für die Kosten der visit-Operationen ist. Fazit: Baumdurchläufe haben lineare Laufzeit. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 65 Levelorder-Durchlauf a 0: c 1: a 2: 3: e d c c d b d f Wunschausgabe: a cd acc edbdf zeilenweise von links nach rechts“ ” Benutze Queue Q, die Zeiger/Referenzen auf Binärbaumknoten speichern kann. FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 66 Prozedur Leveldurchlauf (leere äußere Knoten) Eingabe: v: node; // Wurzel (1) Q: Queue für node; (2) count ← 0; (3) if v <> NIL then // entdecke v (4) count++; v.lnum ← count; (5) v.level ← 0; enqueue(v); (6) while not Q.isempty repeat (7) w ← Q.first; Q.dequeue; (8) visit(w); // bearbeite w (9) p ← w.leftchild; (10) if p <> NIL then (11) count++; p.lnum ← count; // entdecke p (12) p.level ← w.level + 1; enqueue(p); (13) p ← w.rightchild; (14) if p <> NIL then (15) count++; p.lnum ← count; // entdecke p (16) p.level ← w.level + 1; enqueue(p); FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 67 Behauptung 3.4.2 Lineare Zeit, Korrektheit“ ” (a) Levelorder-Durchlauf benötigt Zeit n · tvisit + O(n), wobei tvisit die Zeit für visit angibt. (b) Der Levelorder-Durchlauf ordnet jedem Binärbaumknoten v (in v.level) korrekt seine Tiefe zu. Beweis: Man zeigt durch Induktion über das Level von v: Jeder innere Knoten v des Binärbaums wird genau einmal in die Queue eingefügt, genau einmal entnommen und im Schleifenrumpf (7)-(16) bearbeitet. Dabei wird die korrekte Levelnummer vergeben. Weil Queue-Operationen Zeit O(1) benötigen, ist der restliche Zeitbedarf O(n). FG KTuEA, TU Ilmenau Algorithmen und Datenstrukturen – SS17 – Kapitel 3 68