Einführung Elementare Datenstrukturen (Folie 38, Seite 23 im Skript) Der Konstruktor muß den Listenkopf head erzeugen. Der Vorgänger und Nachfolger von head ist head selbst.
Einführung Elementare Datenstrukturen (Folie 38, Seite 23 im Skript) Der Konstruktor muß den Listenkopf head erzeugen. Der Vorgänger und Nachfolger von head ist head selbst. Java public class ADList K, D extends AbstractMap K, D { private Listnode K, D head; public ADList() { head = new Listnode K, D (null, null); head.pred = head; head.succ = head; }
Einführung Elementare Datenstrukturen (Folie 39, Seite 23 im Skript) Java public class Listnode K, D { K key; D data; Listnode K, D pred, succ; Listnode(K k, D d) { key = k; data = d; pred = null; succ = null; } void delete() { pred.succ = succ; succ.pred = pred; } void copy(listnode K, D n) { key = n.key; data = n.data; } void append(listnode K, D newnode) { newnode.succ = succ; newnode.pred = this; succ.pred = newnode; succ = newnode; }
Einführung Elementare Datenstrukturen (Folie 40, Seite 23 im Skript) Java Java Java public void append(k k, D d) { head.pred.append(new Listnode K, D (k, d)); } public void prepend(k k, D d) { head.append(new Listnode K, D (k, d)); } public void delete(k k) { Listnode K, D n = findnode(k); if(n null) n.delete(); }
Einführung Elementare Datenstrukturen (Folie 41, Seite 23 im Skript) Java Java public D find(k k) { Listnode K, D n = findnode(k); if(n == null) return null; return n.data; } protected Listnode K, D findnode(k k) { Listnode K, D n; head.key = k; for(n = head.succ;!n.key.equals(k); n = n.succ) { } head.key = null; if(n == head) return null; return n; }
Einführung Elementare Datenstrukturen Einfach verkettete Listen (Folie 42, Seite 24 im Skript) Kein Zeiger auf Vorgänger Einfachere Datenstruktur Operationen können komplizierter sein Frage: Wie kann ein Element vor einen gegebenen Knoten eingefügt werden? Ersetzen und alten Knoten anfügen! Vorsicht: Eine gefährliche Technik.
Einführung Elementare Datenstrukturen Einfach verkettete Listen (Folie 42, Seite 24 im Skript) Kein Zeiger auf Vorgänger Einfachere Datenstruktur Operationen können komplizierter sein Frage: Wie kann ein Element vor einen gegebenen Knoten eingefügt werden? Ersetzen und alten Knoten anfügen! Vorsicht: Eine gefährliche Technik.
Einführung Elementare Datenstrukturen Listen Laufzeit (Folie 43, Seite 25 im Skript) Manche Operation sind schnell, manche langsam... Operation Laufzeit append() Θ(1) delete() Θ(1) delete() Θ(n) find() Θ(n) insert() Θ(n) direktes Löschen eines Knotens, nicht über Schlüssel
Einführung Elementare Datenstrukturen (Folie 44, Seite 27 im Skript) Java public class Stack D { private ADList Object, D stack; private int size; public Stack() { stack = new ADList Object, D (); size = 0; } public boolean isempty() { return size == 0; } public D pop() { D x = stack.firstnode().getdata(); stack.firstnode().delete(); size ; return x; } public void push(d x) { stack.prepend(null, x); size++; } public int size() { return size; } }
Einführung Elementare Datenstrukturen (Folie 45, Seite 27 im Skript) Java public class Queue D { private ADList Object, D queue; private int size; public Queue() { queue = new ADList Object, D (); size = 0; } public D dequeue() { D x = queue.lastnode().getdata(); queue.lastnode().delete(); size ; return x; } public void enqueue(d x) { queue.prepend(null, x); size++; } public int size() { return size; } }
Übersicht 1 Einführung 2 3 Graphalgorithmen 4 Algorithmische Geometrie 5 Textalgorithmen 6 Paradigmen
Übersicht 2 Binäre Suchbäume Hashing Skip-Lists Mengen Sortieren Order-Statistics
Lineare Suche (Folie 46, Seite 30 im Skript) Wir suchen x im Array a[0,..., n 1] Algorithmus function find1(int x) boolean : for i = 0 to n 1 do if x = a[i] then return true fi od; return false Die innere Schleife ist langsam.
Lineare Suche verbessert (Folie 47, Seite 31 im Skript) Wir verwenden ein Sentinel-Element am Ende. Das Element a[n] muß existieren und unbenutzt sein. Algorithmus function find2(int x) boolean : i := 0; a[n] := x; while a[i] x do i := i + 1 od; return i < n Die innere Schleife ist sehr schnell.
Lineare Suche ohne zusätzlichen Platz (Folie 48, Seite 31 im Skript) Algorithmus function find3(int x) boolean : if x = a[n 1] then return true fi; temp := a[n 1]; a[n 1] := x; i := 0; while a[i] x do i := i + 1 od; a[n 1] := temp; return i < n 1 Erheblicher Zusatzaufwand. Innere Schleife immer noch sehr schnell.
Lineare Suche Analyse (Folie 49, Seite 32 im Skript) Wieviele Vergleiche benötigt eine erfolgreiche Suche nach x im Mittel? Wir nehmen an, daß jedes der n Elemente mit gleicher Wahrscheinlichkeit gesucht wird. Es gilt Pr[x = a[i]] = 1/n für i {0,..., n 1}. Sei C die Anzahl der Vergleiche: C = i + 1 gdw. x = a[i]
Lineare Suche Analyse (Folie 49, Seite 32 im Skript) Wieviele Vergleiche benötigt eine erfolgreiche Suche nach x im Mittel? Wir nehmen an, daß jedes der n Elemente mit gleicher Wahrscheinlichkeit gesucht wird. Es gilt Pr[x = a[i]] = 1/n für i {0,..., n 1}. Sei C die Anzahl der Vergleiche: C = i + 1 gdw. x = a[i]
Lineare Suche Analyse (Folie 50, Seite 32 im Skript) Wir suchen den Erwartungswert von C. Pr[C = i] = 1/n für i = 1,..., n E(C) = n k Pr[C = k] = k=1 Es sind im Mittel (n + 1)/2 Vergleiche. n k=1 k n = n + 1 2
Lineare Suche Analyse (Folie 50, Seite 32 im Skript) Wir suchen den Erwartungswert von C. Pr[C = i] = 1/n für i = 1,..., n E(C) = n k Pr[C = k] = k=1 Es sind im Mittel (n + 1)/2 Vergleiche. n k=1 k n = n + 1 2
Lineare Suche Analyse (Folie 51, Seite 32 im Skript) Unser Ergebnis: Es sind im Mittel (n + 1)/2 Vergleiche. Ist das Ergebnis richtig? Wir überprüfen das Ergebnis für kleine n. n = 1? n = 2?
Lineare Suche Analyse (Folie 51, Seite 32 im Skript) Unser Ergebnis: Es sind im Mittel (n + 1)/2 Vergleiche. Ist das Ergebnis richtig? Wir überprüfen das Ergebnis für kleine n. n = 1? n = 2?
Binäre Suche (Folie 52, Seite 33 im Skript) Wir suchen wieder x in a[0,..., n 1]. Algorithmus function binsearch(int x) boolean : l := 0; r := n 1; while l r do m := (l + r)/2 ; if a[m] < x then l := m + 1 fi; if a[m] > x then r := m 1 fi; if a[m] = x then return true fi od; return false Wir halbieren den Suchraum in jedem Durchlauf.
Binäre Suche (Folie 53, Seite 33 im Skript) Java static public boolean binsearch(int x, int[ ] a) { int l = 0, r = a.length 1, m, c; while(l r) { m = (l + r)/2; if(x == a[m]) return true; if(x < a[m]) r = m 1; else l = m + 1; } return false; }
Binäre Suche Analyse (Folie 54, Seite 33 im Skript) Java function binsearch(int x) boolean : l := 0; r := n 1; while l r do m := (l + r)/2 ; if a[m] > x then l := m + 1 fi; if a[m] < x then r := m 1 fi; if a[m] = x then return true fi od; return false Es sei n = r l + 1 die Größe des aktuellen Unterarrays. Im nächsten Durchgang ist die Größe m l oder r m.
Binäre Suche Analyse (Folie 55, Seite 34 im Skript) Lemma Es sei a R und n N. Dann gilt 1 a + n = a + n 2 a + n = a + n 3 a = a
Binäre Suche Analyse (Folie 56, Seite 34 im Skript) Im nächsten Durchlauf ist die Größe des Arrays m l oder r m. Hierbei ist m = (l + r)/2. Die neue Größe ist also m l = (l + r)/2 l = (r l)/2 = (n 1)/2 oder r m = r (l + r)/2 = (r l)/2 = (n 1)/2. Im schlimmsten Fall ist die neue Größe des Arrays (n 1)/2.
Rekursionsgleichung für binäre Suche (Folie 57, Seite 34 im Skript) Sei S n die Anzahl der Schleifendurchläufe im schlimmsten Fall bei einer erfolglosen Suche. Wir erhalten die Rekursionsgleichung { 0 falls n < 1, S n = 1 + S (n 1)/2 falls n 1. Die ersten Werte sind: n 0 1 2 3 4 5 6 7 8 S n 0 1 2 2 3 3 3 3 4 Wir suchen eine geschlossene Formel für S n.
Rekursionsgleichung für binäre Suche (Folie 57, Seite 34 im Skript) Sei S n die Anzahl der Schleifendurchläufe im schlimmsten Fall bei einer erfolglosen Suche. Wir erhalten die Rekursionsgleichung { 0 falls n < 1, S n = 1 + S (n 1)/2 falls n 1. Die ersten Werte sind: n 0 1 2 3 4 5 6 7 8 S n 0 1 2 2 3 3 3 3 4 Wir suchen eine geschlossene Formel für S n.
Lösen der Rekursionsgleichung (Folie 58, Seite 34 im Skript) Wir betrachten den Spezialfall n = 2 k 1: (2 k 1) 1 2 k 2 = = 2 k 1 1 = 2 k 1 1. 2 2 Daher: S 2 k 1 = 1 + S 2 k 1 1 für k 1 S 2 k 1 = k + S 2 0 1 = k
Lösen der Rekursionsgleichung (Folie 58, Seite 34 im Skript) Wir betrachten den Spezialfall n = 2 k 1: (2 k 1) 1 2 k 2 = = 2 k 1 1 = 2 k 1 1. 2 2 Daher: S 2 k 1 = 1 + S 2 k 1 1 für k 1 S 2 k 1 = k + S 2 0 1 = k
Lösen der Rekursionsgleichung (Folie 58, Seite 34 im Skript) Wir betrachten den Spezialfall n = 2 k 1: (2 k 1) 1 2 k 2 = = 2 k 1 1 = 2 k 1 1. 2 2 Daher: S 2 k 1 = 1 + S 2 k 1 1 für k 1 S 2 k 1 = k + S 2 0 1 = k
Binäre Suche Analyse (Folie 59, Seite 35 im Skript) n 0 1 2 3 4 5 6 7 8 S n 0 1 2 2 3 3 3 3 4 Vermutung: S 2 k = S 2 k 1 + 1 S n steigt monoton S n = k, falls 2 k 1 n < 2 k. Oder falls k 1 log n < k. Dann wäre S n = log n + 1.
Binäre Suche Analyse (Folie 59, Seite 35 im Skript) n 0 1 2 3 4 5 6 7 8 S n 0 1 2 2 3 3 3 3 4 Vermutung: S 2 k = S 2 k 1 + 1 S n steigt monoton S n = k, falls 2 k 1 n < 2 k. Oder falls k 1 log n < k. Dann wäre S n = log n + 1.
Binäre Suche Analyse (Folie 59, Seite 35 im Skript) n 0 1 2 3 4 5 6 7 8 S n 0 1 2 2 3 3 3 3 4 Vermutung: S 2 k = S 2 k 1 + 1 S n steigt monoton S n = k, falls 2 k 1 n < 2 k. Oder falls k 1 log n < k. Dann wäre S n = log n + 1.
Binäre Suche Analyse (Folie 60, Seite 35 im Skript) Wir vermuten S n = log n + 1 für n 1. Induktion über n: S 1 = 1 = log 1 + 1 n > 1: Noch zu zeigen: S n = 1 + S (n 1)/2 I.V. = 1 + log (n 1)/2 + 1. log n = log (n 1)/2 + 1 Übungsaufgabe.
Binäre Suche Analyse (Folie 60, Seite 35 im Skript) Wir vermuten S n = log n + 1 für n 1. Induktion über n: S 1 = 1 = log 1 + 1 n > 1: Noch zu zeigen: S n = 1 + S (n 1)/2 I.V. = 1 + log (n 1)/2 + 1. log n = log (n 1)/2 + 1 Übungsaufgabe.
Binäre Suche Analyse (Folie 60, Seite 35 im Skript) Wir vermuten S n = log n + 1 für n 1. Induktion über n: S 1 = 1 = log 1 + 1 n > 1: Noch zu zeigen: S n = 1 + S (n 1)/2 I.V. = 1 + log (n 1)/2 + 1. log n = log (n 1)/2 + 1 Übungsaufgabe.
Binäre Suche Analyse (Folie 60, Seite 35 im Skript) Wir vermuten S n = log n + 1 für n 1. Induktion über n: S 1 = 1 = log 1 + 1 n > 1: Noch zu zeigen: S n = 1 + S (n 1)/2 I.V. = 1 + log (n 1)/2 + 1. log n = log (n 1)/2 + 1 Übungsaufgabe.
Binäre Suche Analyse (Folie 60, Seite 35 im Skript) Wir vermuten S n = log n + 1 für n 1. Induktion über n: S 1 = 1 = log 1 + 1 n > 1: Noch zu zeigen: S n = 1 + S (n 1)/2 I.V. = 1 + log (n 1)/2 + 1. log n = log (n 1)/2 + 1 Übungsaufgabe.
Binäre Suche Analyse (Folie 61, Seite 35 im Skript) Theorem Binäre Suche benötigt im schlimmsten Fall genau viele Vergleiche. Die Laufzeit ist O(log n). log n + 1 = log(n) + O(1)