Algorithmen und Datenstrukturen 7. Vorlesung v h1 Martin Dietzfelbinger 23. Mai 2005 Tv,1 Tv,2 h 2 bal(v) = h2 − h1 ∈ {1, 0, −1}. Definition Ein höhenbalancierter binärer Suchbaum heißt AVL-Baum. FG KTuEA, TU Ilmenau AuD – 23.05.2005 FG KTuEA, TU Ilmenau AVL delete AuD – 23.05.2005 1 Tiefe 5 Effekt: 12 Knoten Lösche wie bei gewöhnlichem BSB: Fälle, DeleteMin Zentraler Effekt: Ein Knoten u wird entfernt, dem mindestens ein Unterbaum fehlt. Tiefe 6 20 Knoten Wenn Balancebedingung nicht verletzt: fertig. Wenn Balancebedingung verletzt, laufe den Weg von u zur Wurzel, teste an jedem Knoten die Balancebedingung, führe gegebenenfalls eine Einfach- oder Doppelrotation aus. Achtung: Möglicherweise auf mehreren Levels nacheinander Rotation nötig. Hier wurde ein Fehler korrigiert Beispiel: Fibonacci-Bäume“ ” FG KTuEA, TU Ilmenau AuD – 23.05.2005 Entfernen des höchsten Blattes in einem minimal großen AVLBaum löst Rotationskaskade aus. 2 FG KTuEA, TU Ilmenau AuD – 23.05.2005 3 2. Fall: T.key = x AVL delete Eingabe: T: AVL tree, x: key und (T.left = NIL oder T.right = NIL) Ausgabe: T: AVL tree, shallower: boolean Entferne Wurzelknoten! 1. Fall: T = NIL x (∗ Erfolglose Suche, Schlüssel x nicht da! ∗) war und ist AVLBaum Keine Rebalancierung nötig! return (T, false) Falls T.left = NIL: T ← T.right Falls T.right = NIL: T ← T.left return (T, true) FG KTuEA, TU Ilmenau AuD – 23.05.2005 4 Fall 2: T.key = x beide Unterbäume nicht leer 5 (T.left,left_shallower) <- AVL_delete(T.left,x) Rebalancierung_links; Fall 4: T.key < x kleiner y (T.right,right_shallower) <- AVL_delete(T.right,x) Rebalancierung_rechts; (T.right,y,s,right_shallower) ← AVL_deletemin(T.right) T.data ← s; T.key ← y; Rebalancierung_rechts; AuD – 23.05.2005 AuD – 23.05.2005 Fall 3: T.key > x x FG KTuEA, TU Ilmenau FG KTuEA, TU Ilmenau 6 FG KTuEA, TU Ilmenau AuD – 23.05.2005 7 In AVL deletemin: In AVL deletemin: Fall A: T.left = NIL Fall B: T.left <> NIL: Wurzel entfernen y ← T.key; s ← T.data; T ← T.right; return (T, y, s, true) bleibt AVL-Baum (T.left,y,s,left_shallower) ← AVL_deletemin(T.left); Rebalancierung_links; (∗ gibt shallower einen Wert ∗) return (T,y,s,shallower) FG KTuEA, TU Ilmenau AuD – 23.05.2005 8 T1 T1 9 Aktion 1.Fall: left_shallower = false shallower <- false; T: T2 AuD – 23.05.2005 Fall Rebalancierung links: (Rebalancierung rechts geht symmetrisch) T: FG KTuEA, TU Ilmenau 2. Fall: left_shallower = true ∧ T.bal = -1 T2 umgebaut zu Rückgabewerte: Neuer Baum und Boolean shallower“ ” shallower <- true; T.bal <- 0; geschrumpft FG KTuEA, TU Ilmenau AuD – 23.05.2005 10 FG KTuEA, TU Ilmenau AuD – 23.05.2005 11 Fall Aktion 4.Fall: left_shallower = true ∧ T.bal = 1 3.Fall: left_shallower = true ∧ T.bal = 0 T1 shallower <-false; T.bal <- 1; Unterfälle je nach Aussehen von T2. T2 ist nicht leer! geschrumpft FG KTuEA, TU Ilmenau AuD – 23.05.2005 T2 12 Fall 4.1: T.right.bal = 0; FG KTuEA, TU Ilmenau 13 Fall 4.2: T.right.bal = 1; T T AuD – 23.05.2005 T T T.left T.right T1 T1 T2 T2 T2 T1 T2 T <- left_rotate(T); T.left.bal <- 1; Linksrotation! T.bal <- -1; shallower <- false; Hier wurde ein Fehler korrigiert! FG KTuEA, TU Ilmenau AuD – 23.05.2005 T2 T2 T1 T2 T2 T <- left_rotate(T); T.left.bal <- 0; Linksrotation! T.bal <- 0; shallower <- true; 14 FG KTuEA, TU Ilmenau AuD – 23.05.2005 15 Fall 4.3: T.right.bal = -1; Fall 4.3 (Forts.) Betrachte Teilbäume von T2 = T.right. T T T: T1 T1 T3 T3 T2 T2 T1 T3 T2 Doppelrotation! T <- right_left_rotate(T); shallower <- true; Neue Werte: FG KTuEA, TU Ilmenau altes T.bal −1 0 1 AuD – 23.05.2005 16 17 Die Prozedur hat Laufzeit O(log n) und führt an jedem Knoten auf dem Weg von der Wurzel zum gelöschten Knoten höchstens eine Einfach- oder Doppelrotation durch. Hier wurde ein Fehler korrigiert! (Spaltenüberschriften vertauscht) Satz In AVL-Bäumen kostet jede Wörterbuchoperation Zeit Das alte T.bal enthält (nach der Doppelrotation) den Balancefaktor, der ursprünglich in der Wurzel des zentralen“ Unterbaums stand. ” AuD – 23.05.2005 AuD – 23.05.2005 Proposition Die rekursive Prozedur AVL delete führt die Wörterbuchoperation delete korrekt durch. D.h.: es entsteht wieder ein AVL-Baum. T.left.bal T.right.bal T.bal 0 1 0 0 0 0 −1 0 0 FG KTuEA, TU Ilmenau FG KTuEA, TU Ilmenau O(log n), wo n die Anzahl der Wörterbucheinträge ist. 18 FG KTuEA, TU Ilmenau AuD – 23.05.2005 19 Mehrweg-Such-Bäume Mehrweg-Such-Bäume Bäume aus Knoten mit variablem Ausgrad Beispiel eines N-MSB: Knoten mit mehreren Unterbäumen: Wurzel x1 xl 27 39 7 T0 T1 Tl-1 16 29 35 36 38 45 Tl 1 x1 < · · · < xl. 2 4 Für yi in Ti, 0 ≤ i ≤ l: 10 11 13 9 21 25 41 48 50 12 y0 < x1 < y1 < x2 < · · · < yl−1 < xl < yl FG KTuEA, TU Ilmenau AuD – 23.05.2005 20 FG KTuEA, TU Ilmenau Mehrweg-Such-Bäume AuD – 23.05.2005 21 Mehrweg-Such-Bäume Definition Mehrweg-Suchbäume (MSBe) über dem (angeordneten) Universum U sind wie folgt induktiv definiert: Möglichkeit für Implementierung eines Knotens: Variante 1: (0) Der leere Baum ist ein U -MSB. 1 (1) Ist l ≥ 1 und sind x1 < x2 < · · · < xl Schlüssel in U und sind T0, T1, . . . , Tl U -MSBe mit: Für yi in Ti, 0 ≤ i ≤ l: y0 < x1 < y1 < x2 < · · · < yl−1 < xl < yl l: 3 0 1 AuD – 23.05.2005 22 4 l max 5 l_max: 9 2 3 4 5 l max sons: dann ist auch (T0, x1, T1, x2, . . . , xl−1, Tl−1, xl, Tl) ein U Mehrweg-Suchbaum. FG KTuEA, TU Ilmenau 2 3 keys: 10 11 13 FG KTuEA, TU Ilmenau AuD – 23.05.2005 23 Mehrweg-Such-Bäume Mehrweg-Such-Bäume Möglichkeit für Implementierung eines Knotens: Variante 2: keys: 10 11 Variante 3: 1 MSB-Knoten wird durch aufsteigend sortierte lineare Liste von Binärbaumknoten dargestellt. Im Knoten muss als boolescher Wert vermerkt sein, ob es sich um den Knoten am Listenende handelt. (Im Bild: *“.) ” Elegant: Für die Suche kann man die gewöhnliche Suchprozedur für binäre Suchbäume benutzen. 13 sons: l: 3 FG KTuEA, TU Ilmenau AuD – 23.05.2005 24 FG KTuEA, TU Ilmenau Mehrweg-Such-Bäume AuD – 23.05.2005 25 2-3-Bäume Definition Ein Mehrweg-Suchbaum T heißt ein 2-3-Baum, wenn gilt: T: 39 * 27 7 1 2 4 * (a) Jeder Knoten enthält 1 oder 2 Schlüssel (also hat jeder Knoten 2 oder 3 Unterbäume, was der Struktur den Namen gibt); 16 * 10 9 * 11 13 * 21 25 * 12 * (b) Für jeden Knoten v in T gilt: wenn v einen leeren Unterbaum hat, so sind alle Unterbäume unter v leer, d.h. v ist dann Blatt; (c) Alle Blätter von T haben dieselbe Tiefe. FG KTuEA, TU Ilmenau AuD – 23.05.2005 26 FG KTuEA, TU Ilmenau AuD – 23.05.2005 27 2-3-Bäume 2-3-Bäume Beispiele: Beispiele: Leerer 2-3-Baum: I G 2-3-Baum mit 2 Ebenen: G O I O T Level 1 Level 1 A A Level 2 L R H M L R S U Level 0 = Blattebene Level 0 = Blattebene NB: Die Ebenen werden von den Blättern her numeriert. FG KTuEA, TU Ilmenau AuD – 23.05.2005 28 FG KTuEA, TU Ilmenau AuD – 23.05.2005 2-3-Bäume L A O 29 2-3-Bäume G T M R A U O L M R Kein 2-3-Baum (zu großer Grad). Kein 2-3-Baum (Blätter in verschiedenen Tiefen). FG KTuEA, TU Ilmenau AuD – 23.05.2005 30 FG KTuEA, TU Ilmenau AuD – 23.05.2005 31 2-3-Bäume G A I 2-3-Bäume: Logarithmische Tiefe Proposition O Die Tiefe eines 2-3-Baums mit n Daten ist mindestens dlog3(n + 1)e − 1 und höchstens blog(n + 1)c − 1. [log3 x ≈ 0.63 log2 x] L Level h Kein 2-3-Baum (Leerer Unterbaum in Nicht-Blatt). h-1 1 0 FG KTuEA, TU Ilmenau AuD – 23.05.2005 32 Suche in 2-3-Bäumen: Rekursiv FG KTuEA, TU Ilmenau AuD – 23.05.2005 33 Suche in 2-3-Bäumen: Rekursiv lookup(T, x), für 2-3-Baum T , x ∈ U . 2a: x < x1: Rufe lookup für ersten Unterbaum T0 auf. 1. Fall: T = . Ausgabe: ↑ 2. Fall: Die Wurzel von T enthält Schlüssel x1 (und eventuell x2 > x1). 2b: x = x1: gefunden“. ” 2c: x1 < x und ( x2 existiert nicht oder x < x2): Rufe lookup für zweiten Unterbaum T1 auf. 2d: x2 existiert und x = x2: gefunden“. ” 2e: x2 existiert und x2 < x: Rufe lookup für dritten Unterbaum T2 auf. FG KTuEA, TU Ilmenau AuD – 23.05.2005 34 FG KTuEA, TU Ilmenau AuD – 23.05.2005 35 Suche in 2-3-Bäumen: Rekursiv Einfügen in 2-3-Bäumen: Rekursiv Klar: Zeitaufwand: Wenn x im Knoten vx sitzt: Für jeden Knoten v auf dem Weg von der Wurzel zu vx entstehen Kosten O(1). ⇒ Zeit für Suche ist O(log n). insert(T, x), für 2-3-Baum T , x ∈ U . Resultat: Neuer Baum T 0, Boolescher Wert higher, der angibt, ob T 0 höher als T ist. Invariante (I): (Benutzen – Kontrollieren): T 0 höher als T ⇒ T 0 hat in der Wurzel nur einen Schlüssel. 1. Fall: T = . Erzeuge neuen 2-3-Baum-Knoten mit 1 Eintrag x, 2 leeren Unterbäumen (Blatt!) return (t, true) (I) stimmt. FG KTuEA, TU Ilmenau AuD – 23.05.2005 36 Einfügen in 2-3-Bäumen: Rekursiv 2. Fall: Wurzel von T enthält Schlüssel x1 und eventuell x2 > x1, entsprechend Unterbäume T0, T1 und eventuell T2. 2a: x < x1: insert(T0) liefert T00 und sub higher. Rebalancierung (s.u.). FG KTuEA, TU Ilmenau AuD – 23.05.2005 37 2d: x2 existiert und x = x2: Update. higher ← false; 2e: x2 existiert und x2 < x: insert(T2) liefert T20 und sub higher. Rebalancierung (s.u.). 2b: x = x1: Update. higher ← false; 2c: x1 < x und ( x2 existiert nicht oder x < x2): insert(T1) liefert T10 und sub higher. Rebalancierung (s.u.). FG KTuEA, TU Ilmenau AuD – 23.05.2005 38 FG KTuEA, TU Ilmenau AuD – 23.05.2005 39 Einfügen in 2-3-Bäumen: Rebalancierung Einfügen in 2-3-Bäumen: Rebalancierung Fälle 2a/2c/2e: Fall 2a(ii)/2c(ii): Fall 2a(i)/2c(i)/2e(i): sub_higher = false. x2 existiert nicht und sub_higher = true Der veränderte Teilbaum ist nicht tiefer geworden. 2a(ii): Benutze (I)! Keine weitere Rebalancierung nötig: Setze higher ← false. x1 T T0 Umbau z T x1 z alt T1 neu, tiefer T00 T00 T01 T1 T01 higher ← false FG KTuEA, TU Ilmenau AuD – 23.05.2005 40 Einfügen in 2-3-Bäumen: Rebalancierung 41 Fall 2a(iii)/2c(iii)/2e(iii): x2 existiert nicht und sub_higher = true x1 T1 alt AuD – 23.05.2005 Einfügen in 2-3-Bäumen: Rebalancierung 2c(ii): Benutze (I)! T FG KTuEA, TU Ilmenau Umbau z T0 T x1 Benutze jeweils (I)! z neu, tiefer T0 T10 T10 T11 T11 higher ← false FG KTuEA, TU Ilmenau AuD – 23.05.2005 42 FG KTuEA, TU Ilmenau AuD – 23.05.2005 43 Einfügen in 2-3-Bäumen: Rebalancierung Einfügen in 2-3-Bäumen: Rebalancierung 2a(iii): 2c(iii): T0 x2 x1 T z x1 T x2 T1 T00 T01 T01 T1 T10 T2 AuD – 23.05.2005 44 FG KTuEA, TU Ilmenau Einfügen in 2-3-Bäumen: Rebalancierung T0 x2 T11 T2 Umbau z x1 z T0 T1 45 (a) Die Prozedur insert ist korrekt, d.h. sie erhält die 2-3-BaumStruktur. T1 T21 AuD – 23.05.2005 Beobachtung: 2-3-Bäume wachsen in der Tiefe durch Spalten der Wurzel“. ” Proposition x2 T T20 T10 Einfügen in 2-3-Bäumen 2e(iii): T2 T0 Prüfe: (I) erfüllt. Prüfe: (I) erfüllt. x1 T11 higher ← true higher ← true T x2 T2 T0 FG KTuEA, TU Ilmenau x1 z T2 T1 T00 z T Umbau x2 z Umbau neu, tiefer x1 T T20 (b) Das Einfügen eines Schlüssels in einen 2-3-Baum mit n Schlüsseln benötigt Zeit O(log n) und die Erzeugung von höchstens log2 n neuer Knoten. T21 higher ← true Prüfe: (I) erfüllt. FG KTuEA, TU Ilmenau AuD – 23.05.2005 46 FG KTuEA, TU Ilmenau AuD – 23.05.2005 47 Einfügen in 2-3-Bäumen Löschen in 2-3-Bäumen Beweis: (a) Man kontrolliert in jedem Fall des Algorithmus nach, dass die 2-3-Baum-Struktur wiederhergestellt wird. (b) Für die Bearbeitung eines Levels in der insert-Prozedur wird Zeit O(1) benötigt. Auf jedem der ≤ log n Levels wird höchstens 1 Knoten neu gebildet. Prinzip: Suche den kleinsten Schlüssel y ≥ x, der in einem Blatt gespeichert ist. (x oder der Inorder-Nachfolger von x.) Setze y an die Stelle von x und entferne y. Fazit: Man muss sich nur um das Löschen eines Eintrags y in einem Blatt kümmern. Folgerung: Für jedes n ≥ 0 existiert ein 2-3-Baum mit n Schlüsseln. (Man füge in einen anfangs leeren Baum die Schlüssel 1, . . . , n ein.) FG KTuEA, TU Ilmenau AuD – 23.05.2005 48 FG KTuEA, TU Ilmenau AuD – 23.05.2005 49 Löschen in 2-3-Bäumen Einfacher Fall: Neben y hat das Blatt noch andere Einträge. Keine Umstrukturierung nötig. Hashing Rebalancierungsfall: Durch das Streichen von y wird das Blatt leer, verliert also an Höhe. Ähnlich wie bei den Einfügungen werden flacher gewordene Teilbäume durch lokale Umstellungen wieder auf die Höhe der anderen Teilbäume gebracht. oder Schlüsseltransformationsverfahren Wiederholend lesen: Folien aus GdP1 zu B-Bäumen. FG KTuEA, TU Ilmenau AuD – 23.05.2005 50 FG KTuEA, TU Ilmenau AuD – 23.05.2005 51 Gegeben: Universum U (auch ohne Ordnung) und Wertebereich R. T Ziel: Implementiere Wörterbuch oder 0 1 2 h dynamische (partielle) Abbildung U : Universum der Schlüssel f : S → R, wo S ⊆ U endlich [m] = {0, . . . , m − 1} : Indexbereich für Tabelle T Werden sehen: Erreichbar ist S ⊆ U , |S| = n Zeit O(1) pro Operation im Durchschnitt“ ” Unabhängig vom Umfang der Datenstruktur! S m −1 U Gegensatz Bäume: O(log(n)) FG KTuEA, TU Ilmenau AuD – 23.05.2005 h : U → [m] 52 FG KTuEA, TU Ilmenau AuD – 23.05.2005 53 Beispiel: U = {A, . . . , Z, a, . . . , z}≥3 Grundansatz: Nichtleere Wörter mit mindestens 3 Buchstaben: unendlich! Speicherung in m Plätzen einer Tabelle T[0..m − 1]. Aus Schlüssel x ∈ U wird ein Index h(x) ∈ {0, . . . , m − 1} berechnet. h : U → {0, . . . , 12} wird definiert durch h(c1c2 · · · cr ) = num(c3) x wird in h(x) umgewandelt/transformiert.“ ” Idealvorstellung: Speichere x in Zelle T[i], wo i = h(x). mod 13, wo num(A) = num(a) = 0 num(B) = num(b) = 1 .. .. .. num(Z) = num(z) = 25 FG KTuEA, TU Ilmenau AuD – 23.05.2005 54 FG KTuEA, TU Ilmenau AuD – 23.05.2005 55 h(c1 . . . cr ) = num(c3) mod 13 x Januar Februar Maerz April Mai Juni Juli August September Oktober November Dezember FG KTuEA, TU Ilmenau num(c3) 13 1 4 17 8 13 11 6 15 19 21 25 Definition Eine Funktion h : U → [m] heißt eine Hashfunktion. h(x) 0 1 4 4 8 0 11 6 2 6 8 12 AuD – 23.05.2005 Wenn S ⊆ U gegeben ist (oder ein f : S → R), verteilt h die Schlüssel in S auf [m] = {0, . . . , m − 1}. Idealfall: Die Einschränkung h S ist injektiv, d. h. für jedes i ∈ [m] existiert höchstens ein x ∈ S mit h(x) = i. Beispiel: Auf S = {Februar, Maerz, Mai, Juni, Juli, Dezember} ist obiges h injektiv, nicht aber auf S = {Februar, Maerz, April} 56 Sprechweise: 57 Fall: h rein zufällig“, |S| = n, S = {x1, . . . , xn}. D. h.: ” Uniformitätsannahme (UF∗): Werte h(x1), . . . , h(xn) in {0, . . . , m − 1}n sind rein zufällig“, ” d. h. jeder der mn möglichen Wertevektoren (i1, . . . , in) ∈ {0, . . . , m − 1}n kommt mit derselben Wahrscheinlichkeit 1/mn vor. Falls h perfekt für S: Speichere x bzw. (x, r) in Tabellenplatz T[h(x)]. lookup(x): • Berechne i = h(x). (Dies sollte effizient möglich sein.) • Prüfe, ob in T[i] Schlüssel x steht. Falls ja: (x, r) ausgeben, sonst x ∈ / S“. ” Kollision: x, y ∈ S, x 6= y, h(x) = h(y) AuD – 23.05.2005 AuD – 23.05.2005 Leider sind Kollisionen praktisch unvermeidlich“ ” (Ausweg: speziell auf S abgestimmte Hashfunktion h.) h perfekt für S :⇔ h S injektiv. FG KTuEA, TU Ilmenau FG KTuEA, TU Ilmenau 58 Tritt ein, wenn S ⊆ U rein zufällige Menge ist und h das Universum in jgleich d. h. k große Teile lschneidet, m −1 |U | h ({i}) = |U | oder = m , i = 0, . . . , m − 1. m FG KTuEA, TU Ilmenau AuD – 23.05.2005 59 Mit (UF∗): Prob(h injektiv auf S) ≤ e− Prob(h ist injektiv auf {x1, . . . , xn}) m−n+1 m m−1 m−2 · · · ··· · = m m m m 1 ... = 1 · 1 − m n Auslastungsfaktor“ α = ” m 1 2 n−1 · 1− · ··· · 1 − m m 2 ≤ e0 · e− m · e− m · · · · · e− n−1 m = e− n(n−1) 2m → Kollisionsbehandlung 60 FG KTuEA, TU Ilmenau AuD – 23.05.2005 61 Hashing mit verketteten Listen Beispiel: FG KTuEA, TU Ilmenau . Fazit: Kollisionen kommen vor. Hashing mit verketteten Listen T : α0 (n−1) 2 Winzig für nicht ganz kleine n! . AuD – 23.05.2005 nicht kleiner als eine Konstante α0. Dann: Prob(h injektiv auf S) ≤ e− (denn für x 6= 0 ist 1 + x < ex), also . . . FG KTuEA, TU Ilmenau . Wunsch: Linearer Platzverbrauch, also (Für i = 1, . . . , n ist die Wahrscheinlichkeit, dass h(xi) in [m] − {h(x1), . . . , h(xi−1)} liegt, genau m−i+1 m .) n(n−1) 2m engl.: chained hashing 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: AuD – 23.05.2005 Juni Februar September Januar Maerz April August Oktober November Mai Benutze Array T[0..m − 1] von Zeigern auf Anfänge von m einfach verketteten linearen Listen L0, . . . , Lm−1. Liste Li enthält die Schlüssel aus Behälter“ ( bucket“) ” ” Bi = {x ∈ S | h(x) = i}, u. U. mit Zusatzinformation, d. h. dem Wert r = f (x). Juli Dezember 62 FG KTuEA, TU Ilmenau AuD – 23.05.2005 63 insert(x, r): Berechne i = h(x); suche Schlüssel x in Liste bei T[i]; falls gefunden: ersetze Daten bei x durch r; sonst: füge (x, r) in Liste T[i] ein. Kosten: O(1 + Zahl der Schlüsselvergleiche x = x0?“) ” . . . falls die Auswertung von h(x) und ein Schlüsselvergleich Zeit O(1) kostet. Algorithmen(skizzen) empty (m): Erzeugt Array T[0..m-1] mit m NIL-Zeigern und legt h : U → [m] fest. Kosten: Θ(m). Beachte: Man wählt h, ohne S zu kennen! 1. Fall: x nicht vorhanden — erfolglose Suche“ ” Zahl der Schlüsselvergleiche = |Bi|. 2. Fall: x ist vorhanden — erfolgreiche Suche“ ” Mittlere Zahl der Schlüsselvergleiche = 12 |Bi|. FG KTuEA, TU Ilmenau AuD – 23.05.2005 64 delete(x): Berechne i = h(x); suche Schlüssel x in Liste bei T[i]; falls gefunden: lösche Eintrag; sonst: tue nichts. 65 Nun: Suche nach y ∈ U . α= n m: der (aktuelle) Auslastungsfaktor. Fall 1: y ∈ / S — erfolglose Suche. Ziel: Analysiere erwartete Kosten“. ” Genügt: Analysiere erwartete Anzahl der Schlüsselvergleiche“. ” AuD – 23.05.2005 AuD – 23.05.2005 Szenario: n Schlüssel x1, . . . , xn in Struktur gespeichert, Menge S. Kosten: wie bei insert. FG KTuEA, TU Ilmenau FG KTuEA, TU Ilmenau 66 Wieviele Schlüsselvergleiche im erwarteten Fall“? ” Abgeschwächte Uniformitätsannahme (UF2): Für je 2 Schlüssel x 6= z in U gilt: 1 Prob(h(x) = h(z)) ≤ m FG KTuEA, TU Ilmenau AuD – 23.05.2005 67 Definiere Zufallsgrößen/Zufallsvariable, für x, z ∈ U : 1 falls h(x) = h(z), Yx,z := 0 falls h(x) 6= h(z). Erwartete Listenlänge: E(by ) = x∈S Nach (UF2): E(Yx,z ) = Prob(h(x) = h(z)) ≤ 1 . m X Yx,y . = x∈S 68 Fall 2: y ∈ S — erfolgreiche Suche. x∈S Der erwartete Zeitbedarf für eine erfolglose Suche ist O(1+α). Fazit: Wenn α ≤ α1, α1 konstant (z.B. = 2), dann ist die erwartete Zeit für eine erfolglose Suche O(1). FG KTuEA, TU Ilmenau AuD – 23.05.2005 69 Gemittelt über alle i: Wieviele Schlüsselvergleiche im erwarteten Fall“? ” (nach (UF2)) 1 X X 1 Yxj ,xi = 1 + n n 1 n )! 1≤i≤n j≤i Wir nehmen an: Einfügereihenfolge ist x1, . . . , xn, Elemente werden beim Einfügen ans Listenende gesetzt. X Yxj ,xi . 1≤j<i≤n Erwartungswert (mit (UF2)) ist höchstens Im Fall y = xi wird y mit genau X X 1 n = = α. m m Die erwartete Anzahl von Schlüsselvergleichen bei erfolgloser Suche unter der Annahme (UF2) ist höchstens α. AuD – 23.05.2005 Gemittelt über alle Fälle y = x, x ∈ S (jeweils W. E(Yx,y ) ≤ Proposition Anzahl der Schlüsselvergleiche/Listenlänge: aktuelle Länge der bei der by = |{x ∈ S | h(y) = h(x)}| = Suche zu durchlaufenden Liste FG KTuEA, TU Ilmenau X 1+ Yxj ,y 1 n X 1≤j<i≤n 1 1 (n − 1)n α =1+ <1+ . m n 2m 2 j≤i Listenelementen verglichen. (Vor oder gleich y in der gleichen Liste!) FG KTuEA, TU Ilmenau AuD – 23.05.2005 70 FG KTuEA, TU Ilmenau AuD – 23.05.2005 71 Proposition Einfache Hashfunktionen Die erwartete (mit (UF2)) mittlere (über die Einträge x1, . . . , xn gemittelte) Anzahl von Schlüsselvergleichen bei erfolgreicher Suche ist höchstens 1 + α2 . Kriterien für Qualität: 1) schnelles Auswerten von h(x) Der erwartete Zeitbedarf für eine erfolgreiche Suche ist O(1 + α). 2) wenige Kollisionen (unter realistischen Annahmen über die Schlüsselmenge S) Fazit: Wenn α ≤ α1, α1 konstant (z.B. = 2), dann ist die erwartete Zeit für eine erfolgreiche Suche O(1). Für 1) entscheidend: Schlüsselformat FG KTuEA, TU Ilmenau AuD – 23.05.2005 72 1. Fall: Schlüssel sind natürliche Zahlen: U ⊆ N FG KTuEA, TU Ilmenau AuD – 23.05.2005 73 Multiplikationsmethode: U = {0, 1, . . . , u − 1} Idee: Für 0 < ϑ < 1 (ideal: ϑ irrational) Divisionsrestmethode: h(x) = x mod m Hinweis: Sehr einfach, effizient. Nachteile: h(x) = b((ϑx) mod 1) · mc. • Unflexibel • Bei strukturierten Schlüsselmengen (z.B. aus Strings übersetzte Schlüssel) erhöhtes Kollisionsrisiko • Relativ sicher nur für Primzahlen m. k (Gebrochener Anteil von ϑx.) √ 5 − 1 ≈ 0.618 . . . Beispiel: ϑ = φ − 1 = 12 m = 100 k Vorsichtsmaßnahme: |m − 2 | ≥ 20 für Zweierpotenzen 2 . Für Produktionssysteme nicht sehr zu empfehlen. FG KTuEA, TU Ilmenau AuD – 23.05.2005 Dabei: (ϑx) mod 1 = (ϑx) − b(ϑx)c. 74 FG KTuEA, TU Ilmenau AuD – 23.05.2005 75 Man kann zeigen: Mit diesem ϑ werden aufeinanderfolgende Schlüssel (x, x + 1, . . . , x + q − 1) sehr gut in [m] verteilt. h(100) = b((100ϑ) mod 1) · 100c Diskrete Version“: ” = b(61,80339 . . . mod 1) · 100c ha(x) = (ax mod 2k ) div 2k−l = 80 mit a ungerade und ϑ ≈ a/2k . h(101) = b((101ϑ) mod 1) · 100c = b(62,42339 . . . mod 1) · 100c Auswertung ohne Division (sehr effizient): = 42 a 1 * x = h(x) ax l Bits FG KTuEA, TU Ilmenau AuD – 23.05.2005 76 2. Fall: Schlüssel sind Strings: U ⊆ Seq(Σ) FG KTuEA, TU Ilmenau AuD – 23.05.2005 77 Möglich, nicht sehr zu empfehlen: Transformation von Schlüssel x in Zahl x̂ = n(x) als neuen Schlüssel. Dann: x 7→ h(x̂). Σ: Alphabet“ – endliche nichtleere Menge. ” Beispiel: b {0, 1, . . . , 255} Σ = ASCII-Alphabet = b {0, 1}8 = • Kollisionen n(x) = n(y) nie auflösbar! Schlüssel: x = (c1, . . . , cr ), c1, . . . , cr ∈ Σ. Stets möglich: • Häufig: Ineffiziente Auswertung. 1−1 Besser: An Schlüsselformat x = (c1, . . . , cr ) angepasste Hashfunktionen. num : Σ −→ {0, . . . , |Σ| − 1} übersetzt Alphabetzeichen in Zahlen. FG KTuEA, TU Ilmenau AuD – 23.05.2005 78 FG KTuEA, TU Ilmenau AuD – 23.05.2005 79 Lineare Funktionen über Körper Zp: Lineare Funktionen über Z2-Vektorraum {0, 1}n m = p Primzahl mit p > |Σ|, also 0 ≤ num(c) < p. U = Σr , mit Σ = {0, . . . , s − 1}. Wähle Koeffizienten a1, . . . , ar ∈ {0, . . . , p − 1}. ! r X ai · num(ci) mod p. h(c1 · · · cr ) = m = 2l mit l ≤ w (w: Wortlänge, z. B. w = 32). [m] entspricht {0, 1}l. Repräsentation der Hashfunktion h: i=1 Array A[1..r,0..s − 1] mit Einträgen aus {0, 1}w . Vorteile: • Rechnung nur mit Zahlen < m2 (wenn man nach jeder Multiplikation/Addition modulo m reduziert); • Sehr effizient; • Theoretisch nachweisbares gutes Verhalten, wenn a1, . . . , ar aus {0, 1, . . . , p − 1} zufällig gewählt wurden. FG KTuEA, TU Ilmenau AuD – 23.05.2005 80 Dabei: ⊕ ist bitweises XOR, auf ganzes Wort angewendet. (Maschinenoperation – effizient!) Beispiel: w z }| { 00101101 ⊕ 10110111 10011010 h(c1 · · · cr ) = die ersten l Bits von A[1, num(c1)] ⊕ · · · ⊕ A[r, num(cr )] FG KTuEA, TU Ilmenau AuD – 23.05.2005 81 Vorteile: • Sehr schnelle Auswertung (⊕ ebenso schnell wie +); • Theoretisch nachweisbares gutes Verhalten, wenn Einträge von A zufällig sind; ai XOR bi = ai ⊕ bi 1, ai 6= bi = 0, ai = bi • Dasselbe T kann für m = 24, 25, 26, . . . , 2w benutzt werden. Ideal für die Kombination mit der Verdopplungsstrategie: Wählen einer neuen Hashfunktion für doppelt so große Tabelle entspricht dem Erhöhen von l um 1; die Einträge in A bleiben unverändert. Zahlenbeispiel: r = 20 Zeichen pro Wort. w = 32, Σ = ASCII-Alphabet = b {0, 1}8. A[1..r,0..s − 1] hat rs = 20 · 256 Einträge. Sinnvoll für große Hashtabellen. FG KTuEA, TU Ilmenau AuD – 23.05.2005 82 FG KTuEA, TU Ilmenau AuD – 23.05.2005 83 Wiederholen: GdP1-Folien über Hashing. • Lineares Sondieren • Quadratisches Sondieren • Double Hashing FG KTuEA, TU Ilmenau AuD – 23.05.2005 84