Eidgenössische Technische Hochschule Zürich Ecole polytechnique fédérale de Zurich Politecnico federale di Zurigo Federal Institute of Technology at Zurich Institut für Theoretische Informatik Peter Widmayer Tobias Pröger Thomas Tschager Datenstrukturen & Algorithmen Lösung 5.1 25. März 2015 Lösungen zu Blatt 5 FS 15 AVL-Bäume: Einfügen und Löschen. a) Es ergibt sich der folgende Baum: b) Wird der Schlüssel 20 aus dem Baum aus a) gelöscht, dann hat die Wurzel einen Balancierungsfaktor von 2. Nach der Relancierung ergibt sich der folgende Baum: Lösung 5.2 AVL-Bäume: Maximale Tiefendifferenz zweier Blattknoten. Hat ein AVL-Baum Höhe h, dann können wir die folgenden drei Fälle unterscheiden: • Beide Teilbäume der Wurzel haben Höhe h − 1, • Der linke Teilbaum der Wurzel hat Höhe h − 1, und der rechte hat Höhe h − 2, oder • Der linke Teilbaum der Wurzel hat Höhe h − 2, und der rechte hat Höhe h − 1. Da uns nur Bäume interessieren, die zwei Blätter mit maximaler Tiefendifferenz besitzen, können wir annehmen, dass sich die Höhen der Teilbäume um 1 unterscheiden. O.B.d.A. habe von nun an der linke Teilbaum Höhe h − 1, und der rechte Höhe h − 2. Der linke Teilbaum darf ein beliebiger AVL-Baum der Höhe h − 1 sein, der rechte Teilbaum mit Höhe h − 2 muss die gleichen Eigenschaften wie gerade beschrieben aufweisen (insbesondere muss die Wurzel dieses Baums ebenfalls den Balancierungsfaktor −1 haben, wenn h > 2 ist). Aufgrund dieser Eigenschaften enthält der gesamte Baum ein Blatt mit Tiefe h, und dieses befindet sich im linken Teilbaum. Das Blatt mit der geringsten Tiefe dagegen befindet sich im rechten Teilbaum. Die folgende Abbildung zeigt Beispiele für Bäume der Höhen h ∈ {2, 3, 4}. Allgemein betrachten wir also Bäume mit der folgenden Struktur: Der linke Teilbaum Tl enthält ein Blatt der Tiefe h (welches in Tl Tiefe h − 1 hat), der rechte Teilbaum Tr enthält ein Blatt der Tiefe h − 1 (welches in Tr Tiefe h − 2 hat). Die grösstmögliche Differenz der Tiefen zweier Blätter im gesamten Baum (mit Höhe h) ist daher um 1 grösser als die grösstmögliche Differenz der Tiefen zweier Blätter im rechten Teilbaum (mit Höhe h − 2). Für h = 2 und h = 3 ist die maximale Tiefendifferenz genau 1. Damit ergibt sich die folgende rekursive Formel für die maximale Differenz der Tiefen zweier Blätter in einem Baum der Höhe h: D(2) = 1, D(3) = 1, D(h) = 1 + D(h − 2) für alle h ≥ 4. (1) Man erhält die Vermutung, dass D(h) = bh/2c gilt. Wir beweisen diese Vermutung mittels allgemeiner Induktion über h. Induktionsverankerung I (h = 2): Es gilt D(2) = 1 = b2/2c. Induktionsverankerung II (h = 3): Es gilt D(3) = 1 = b3/2c. Induktionsannahme: Angenommen, D(h − 2) = b(h − 2)/2c. Induktionsschluss ((h − 2) → h): Aufgrund der rekursiven Definition von D(h) gilt (IA) D(h) = 1 + D(h − 2) = 1 + b(h − 2)/2c = 1 + bh/2 − 1c = 1 + bh/2c − 1 = bh/2c. Lösung 5.3 (2) Vereinigung von AVL-Bäumen. Seien T1 und T2 zwei AVL-Bäume der Höhen h1 bzw. h2 . Für einen Baum T bezeichne h(T ) seine Höhe. Die Vereinigung wird wie folgt realisiert: 1) Wir berechnen zunächst die Werte von h1 bzw. h2 , was genau der Länge eines längsten Pfades von der Wurzel zu einem Blatt in T1 bzw. T2 entpricht. Dazu starten wir bei der Wurzel und wählen als Nachfolger eines Knotens v genau den Knoten, an dem der höhere Teilbaum gespeichert ist: Ist bal(v) = −1, fahren wir mit dem linken Nachfolger fort, ansonsten mit dem rechten (für bal(v) = 0 können beide Nachfolger gewählt werden). Die Werte von h1 und h2 können insgesamt in Zeit O(h1 + h2 ) bestimmt werden. 2) Entferne das kleinste Element x aus T2 . Nach der Entfernung ergibt sich ein Baum T20 mit der Höhe h ∈ {h2 − 1, h2 }. Die Operation kann in Zeit O(h2 ) durchgeführt werden. 2 3) Ist |h1 − h| ≤ 1 (die Höhendifferenz von T1 und T20 also maximal 1), dann wird der Algorithmus beendet und ein neuer Baum mit Wurzel x, T1 als linkem Teilbaum und T20 als rechtem Teilbaum zurückgegeben. Für diese Operation fällt nur Zeit O(1) an. 4) Sei nun o.B.d.A. h1 > h + 1 (der Fall h1 < h − 1 verläuft symmetrisch). Wir starten in T1 an der Wurzel und folgen solange dem rechten Nachfolgerknoten, bis wir einen Knoten v finden, der die Wurzel eines Baums T10 mit Höhe h oder h+1 repräsentiert. Wir bestimmen ausserdem den Vorgänger u dieses Knotens v (damit ist T10 der rechte Teilbaum von u, und die Wurzel von T10 ist v). Die Berechnung von u und v können wir wie folgt in Zeit O(h1 ) durchführen. 1 v ← Wurzel(T1 ) 2 h0 ← h1 3 while h0 > h + 1 do 4 u←v 5 if bal(v) = −1 then h0 ← h0 − 2 else h0 ← h0 − 1 6 v ← NachfolgerRechts(v) 5) Ersetze den rechten Teilbaum von u durch den Baum, der x als Wurzel, T10 als linken und T20 als rechten Teilbaum hat. Dieser Baum mit x an der Wurzel ist ein Suchbaum, da alle Schlüssel in T1 (und damit insbesondere in T10 ) kleiner als x sind, und alle Schlüssel aus T20 grösser oder gleich x sind. Er ist sogar ein AVL-Baum, denn der Balancierungsfaktor von x ist h − h0 ∈ {−1, 0}. Analog überlegt man sich, dass der gesamte Baum noch immer ein Suchbaum ist. Lediglich die AVL-Eigenschaft kann verletzt sein, da der neue rechte Teilbaum von u eine Tiefe von h0 + 1 (statt vorher h0 ) besitzt. Wir erhalten den folgenden schematischen Ablauf: Die gesamte Operation kann in Zeit O(1) durchgeführt werden. 3 6) Wie beim Einfügen eines neuen Knotens müssen die Balancierungsfaktoren der Knoten auf dem Pfad von u bis zur Wurzel des Baums geprüft und ggf. durch Rotationen “repariert” werden. Dies kostet maximal Zeit O(h1 ). Insgesamt können die Schritte 1–6 in Zeit O(h1 +h2 ) durchgeführt werden. Da h1 , h2 ∈ O(log n), beträgt die Gesamtlaufzeit also O(log n). 4