Universität Karlsruhe Algorithmentechnik Fakultät für Informatik WS 05/06 ITI Wagner 2. Musterlösung Problem 1: Das Postamtplatzierungsproblem ** Sei OE x 1 x 2 x n. Gesucht ist ein Punkt p = (x, y) mit ( n n ) min w i (p, p i ) = min w i ( x p x i + y p y i ) p p ( n ) n = min w i ( x p x i ) + w i ( y p y i ) p (1) (2) Wir betrachten also zwei unabhängige einimensionale Probleme,.h wir suchen min x n w i (x, x i ) un min y n w i (y, y i ). Wir bestimmen im folgenen ie x-koorinate (für ie y-koorinate ergibt sich eine analoge Berechnung): Falls x i = x j für i j gilt, fassen wir ie beien Gewichte zusammen. Sei W := 1/2 n w i. Für en gewichteten Meian x m er x-werte gilt: w i W w i (3) x i<x m x i>x m Sei W m = n w i(x m, x i ). Betrachte OBA ie linke Seite von x m (rechte Seite ist analog). Es gilt x i<x m w i + w m W. Für jeen Punkt x mit x = x m + gilt: ( ) ( ) W = W m + w i + w m w i (4) x i<x m x i>x m ( ) = W m + w i + w m w i W m (5) x i<x m x i>x m 0 wegen (3) Beachte, ass obige Ungleichung auch ähnlich gilt wenn x x m+1. Sei azu m,m+1 = x m+1 x m W = W m + w i + w m w i w m+1 m,m+1 x i<x m x i>x m+1 über m,m+1 war x m+1 rechts } {{ } 0 wie vorher (sogar schlimmer) + w m+1 ( m,m+1 ) W m 0 nun x m+1 links (6) Somit gilt also x : W Wm Man fine also mit G-Meian (vgl. Übungsblatt 1) in linearer Zeit ie gewichteten Meiane x m un y m. Der Punkt (x m, y m ) ist er gesuchte Punkt p.
Problem 2: Union-Fin *** Da alle Union-Operationen vor allen Fin- un Makeset-Operationen ausgeführt weren, vergrößert sich ie Höhe eines Knoten nach en Union-Operationen nicht mehr. Der Aufwan für ie Union- un Makeset- Operationen liegt in O(m). Danach weren nur noch Fins auf eine Menge von Bäumen angewenet. (a) Zunächst ist klar, ass ie Operationen Union un Makeset insgesamt einen Aufwan in O(m) haben un höchstens m Knoten für nachfolgene Fin-Operationen zur Verfügung stellen. Wie bei er Analyse es allgemeinen Falles, berechnen wir ie Gesamtkosten nach er Ganzheitsmethoe. Dazu teilen teilen wir ie Kosten für ie Fin-Operationen in zwei Teile auf: Für eine Operation Fin(i) seien i = i 0, i 1,..., i l 1, i l ie Knoten auf em Weg von i zur Wurzel i l. Die Pfakompression sorgt afür, ass bei einem Fin(i) für alle Knoten außer i l 1 un i l ie Höhe auf eins verringert wir. Die konstanten Kosten c 1 für i l un i l 1 ornen wir er Fin-Operation zu. Die Kosten für i k mit 0 k l 2 ornen wir em Knoten i k zu, er bei er Fin-Operation bewegt wir. Da jeer Knoten höchstens einmal bewegt wir, ergibt sich für ie Gesamtkosten K aller Fin-Operationen K = Kosten für ie Fins m c 1 Kosten für ie O(m) Fins = O(m) + Kosten für ie Knoten + m c 2 #Knoten #Bewegungen pro Knoten (b) Die obige Analyse macht von er balancing-annahme keinen Gebrauch. Deswegen ergibt sich auch hier Gesamtaufwan O(m). (c) Sei n m ie Anzahl er vorangegangenen Makeset-Operationen. Die Höhe eines Knotens ist hier im schlimmsten Fall in Θ(log n) also kann jee Fin-Operation Aufwan Θ(log n) haben. Damit ergibt sich im schlechtesten Fall ein Gesamtaufwan von Θ(m log n). Setzt man n = m/2, ann ist klar ass er Gesamtaufwan auch in Θ(m log m) ist. Problem 3: Tiefenbestimmungsproblem ** Die folgene Funktion erzeugt einen Baum mit einem Knoten. Algorithmus 1 : Make-Tree(v) Eingabe : Knoten v Ausgabe : Neuer Baum mit Wurzel v [v] := 0 Vor[i] := 1 Algorithmus 2 wir als Subroutine er Algorithmen 3 un 4 aufgerufen. Er liefert zu einem Knoten seine Tiefe un ie Wurzel seines Baumes. Die Funktion Fin-Depth gibt leiglich as erste Argument von Fin zurück. Mit Attach wir ein Baum mit Wurzel v an einem beliebigen Knoten r eines aneren Baums angehängt. Laufzeitanalyse Der Zeitaufwan von Make-Tree bzw. Fin-Depth ist analog zum Zeitaufwan von MakeSet bzw. Fin. Der Aufwan für Attach entspricht em Aufwan für eine Union- un eine Fin- Operation. Der Gesamtaufwan liegt also bei O(2m G(2m)). Wegen er Monotonie von G gilt für alle m: G(2m) G(2 m ) G(m) + 1 2G(m). Daraus folgt G(2m) O(G(m)) un somit liegt er Gesamtaufwan bei O(m G(m)).
Algorithmus 2 : Fin(v) Eingabe : Knoten v Ausgabe : Das Paar (epth(v), r(v)) (Tiefe un Wurzel von v) r := v j := v epth := [v] solange Vor[j] > 0 tue j := Vor[v] epth := epth + [j] r := j Wenn r v // Pfakompression j := v pepth := 0 solange Vor[j] > 0 tue temp := Vor[j] Vor[j] := r [j] := epth pepth pepth := pepth + [j] j := temp (epth(v), r(v)) := (epth, r) Algorithmus 3 : Fin-Depth(v) Eingabe : Knoten v Ausgabe : Die Tiefe epth(v) von v (r, ) := Fin(i) epth(v) := Algorithmus 4 : Attach(r, v) Eingabe : Wurzel v eines Baumes un ein Knoten r Ausgabe : Der Knoten v wir an r angehängt (, q) := Fin(r) z := Vor[r] + Vor[q] // Größe es neuen Baumes Wenn Vor[q] Vor[v] Vor[r] := q [r] := [r] + + 1 Vor[q] := z sonst Vor[q] := r [r] := [r] + + 1 [q] := [r] Vor[r] := z Vor[v] := r
Problem 4: Graustufenbiler ** (a) Der im folgenen angegebene Algorithums bilet für jeen Bilpunkt eine Menge un geht anach ie Matrix Spaltenweise von oben nach unten urch. Dabei wir für jees Element er obere un linke Nachbar in er Matrix (falls vorhanen) auf Äquivalenz geprüft. Sollte sich herausstellen, ass ie Bilpunkte äquivalent sin, so weren ihre Mengen vereinigt. Der Inex ist eine kanonische Abbilung von N N N, a wir für Union-Fin N (1-imensional) als Schlüsselmenge nutzen wollen. 1 2 3 4 Algorithmus 5 : Äquivalenzklassenbilung Eingabe : Die Bilpunke als (m n)-matrix mit en Graustufenwerten als Einträge. Ausgabe : Einteilung er Bilpunkte in Äquivalenzklassen bzgl. er gegebenen Äquivalenzrelation. Für i = 1,..., m Für j = 1,..., n Inex (i, j) := n (j 1) + i Makeset (Inex(i, j)) 5 6 7 8 9 10 Für j = 1,..., n Für i = 1,..., m Wenn grauwert (i, j)=grauwert (i 1, j) Union (Fin(Inex(i, j)), Fin(Inex(i 1, j))) Wenn grauwert (i, j)=grauwert (i, j 1) Union (Fin(Inex(i, j)), Fin(Inex(i, j 1))) (b) Bei jeem Durchlauf er Schleife in Zeile 6 wir ein Bilpunkt (i 0, j 0 ) seiner Äquivalenzklasse zugeornet. Nach jeem solchen Schritt gilt folgene Invariante: i i 0 )} ist seiner Äquivalenz- Jees Element er Menge M := {(i, j) (j < j 0 ) (j = j 0 klasse eingeschränkt auf M zugeornet. Problem 5: -Heaps ** (a) Wir betrachten als Beispielswerte ie Werte von 1 bis 13. Ein 5-Heap bei em ein Vaterknoten einen größeren Wert hat als alle Kinerknoten könnte wie in Abb.1 aussehen. (b) Wie bei binären Heaps sei ein -Heap ein voller -ärer Baum. Ein vollstäniger -ärer Baum er Höhe h hat h 1 + + 2 + + h = i = h+1 1 =: n Knoten. Also gilt hier i=0 h + 1 = log (n() + 1). Demnach ist ie Höhe h(n) eines Baumes mit n Knoten h(n) = log ((n)() + 1) = O(log n). Für festes gilt h(n) = O(log 2 n) (c) Die Nummerierung er Arrayelemente beginne wie in er Vorlesung bei 1. Gesucht wir succ(i, j) im
Baumstruktur : 13 11 10 12 9 8 1 3 5 2 7 6 4 Array : 13 11 10 12 9 8 1 3 5 2 7 6 4 Abbilung 1: Baumstruktur un Arraystruktur eines 5-Heaps -Heap. Sei l ie Tiefe in er Knoten i liegt (wobei l Wurzel = 0). Dann gilt: Der Inex succ(i, j) ist also: Knoten im vollst. Baum bis Tiefe l 1 : l i=0 i = l 1 Knoten vor i innerhalb Tiefe l : i l 1 1 Knoten vor succ(i, j) innerhalb Tiefe l + 1 : (i l 1 1) Knoten im vollst. Baum bis Tiefe l : l+1 1 succ(i, j) = (i l 1 1) + l+1 1 + j = i l+1 + 1 + l+1 1 + j = (i 1) + 1 + j Gesucht wir nun pre(k) im -Heap, aus er Formel für succ(i, j) ergibt sich: k = (i 1) + 1 + j i = k 1 j = k 1 = + 1 k 1 + 1 } {{} >i un i+1 (wegen Absch. rechts) j N >0 un 1 () Heapify funktioniert ganz analog zum binären Fall:
Algorithmus 6 : Heapify(A[1 n], i) Eingabe : Array A, so ass unterhalb vom Inex i ie Heap-Eigenschaft erfüllt ist Ausgabe : Array A, so ass ie Heap-Eigenschaft bis einschließlich i erfüllt ist. k := Succ(i, 1) 1 maxinex := k solange k + 1 <= n tue k := k + 1 Wenn A[k] > A[maxinex] maxinex := k Wenn maxinex i tausche A[i] un A[maxinex] rufe Heapify(A, maxinex) auf (e) Heapify wir wieer höchstens i Mal aufgerufen, wobei i ie Höhe es Unterbaumes von i sei. Da ieser Unterbaum voll ist, gilt i O(log n). Somit ist ie Gesamtlaufzeit von Heapify(A, i) in O(log n) = O(log 2 n).