Kapitel 6: Klassifizierung von Sortiertechniken Sortieren durch 1. Auswählen 2. Einfügen 3. Austauschen 4. Mischen 5. Streuen und Sammeln 6. Fachverteilen G.Heyer 1 Algorithmen und Datenstrukturen Analyse Quicksort worst case: sowohl Vergleiche wie Bewegungen quadratisch. Schlechtester Fall tritt ein, wenn Array bereits sortiert. (N + 1) + (N) + ( N - 1) + ... + 3 Vergleiche best case: Folgen werden in gleichlange Teilfolgen aufgeteilt, Aufrufbaum hat Tiefe log N, auf jeder Ebene maximal N Vergleiche, damit Laufzeit Q(N log N). Mittlere Laufzeit fast so gut wie beste Laufzeit!! Annahmen: Schlüssel 1, ..., N, alle Permutationen gleich wahrscheinlich Average case Komplexität: O(N log N) G.Heyer 2 Algorithmen und Datenstrukturen Shellsort Methode: man sorgt dafür, daß Vertauschungen über größere Abstände möglich werden. Dazu wird abnehmende Folge von Inkrementen h t, ..., h1 definiert, so daß h1 = 1. Eine Folge k1,..., kN heißt h-sortiert, wenn für alle i, 1 i N-h, ki ki+h Array a wird nun mit Einfügesort ht sortiert, dann ht-1 sortiert usw. bis a 1-sortiert und damit sortiert ist. G.Heyer 3 Algorithmen und Datenstrukturen Beispiel: Inkremente 4,2,1 16 9 9 4 4 3 3 3 3 22 11 9 7 4: 4-Sortieren 3 Zuweisungen 3 22 11 16 7 4 3 Zuweisungen 3 4 11 16 7 22: 2-Sortieren 3 Zuweisungen 3 9 11 16 7 22 3 Zuweisungen 3 9 7 16 11 22: 1-Sortieren 3 Zuweisungen 4 9 7 16 11 22 3 Zuweisungen 4 7 9 16 11 22 3 Zuweisungen 4 7 9 11 16 22 G.Heyer 4 Algorithmen und Datenstrukturen Normalverfahren: 16 3 3 3 3 3 3 16 11 9 7 4 22 22 16 11 9 7 11 11 22 16 11 9 9 9 9 22 16 11 7 7 7 7 22 16 4 4 4 4 4 22 3 Zuweisungen 4 Zuweisungen 5 Zuweisungen 6 Zuweisungen 7 Zuweisungen gezählt jeweils 1 Zuweisung an Hilfsspeicher, 1 Zuweisung pro Stelle mit neuem Wert. Problem: Wie wählt man Inkremente richtig? Bei geeigneter Wahl kann man Laufzeit O(N log2 N) erreichen. G.Heyer 5 Algorithmen und Datenstrukturen Heapsort Ein Baum ist ein gerichteter Graph, d.h. eine Struktur bestehend aus Knoten und gerichteten Kanten (Pfeile) zwischen Knoten, so daß gilt: 1) genau ein Knoten besitzt keine eingehende Kante (Wurzel) 2) alle übrigen Knoten besitzen genau 1 eingehende Kante. Ein Baum heißt Binärbaum, wenn alle Knoten entweder 2 oder keine ausgehende Kante besitzen (Knoten ohne ausgehende Kanten heißen Blätter). Ein Binärbaum heißt vollständig, wenn es keinen Binärbaum derselben Tiefe mit mehr Knoten gibt. Die Tiefe ist die Länge des längsten gerichteten Pfades in einem Baum. Ein Heap H (deutsch: Halde) ist ein Baum, für den folgendes gilt: 1) Sei n die Tiefe von H. Bis zur Tiefe n-1 ist H vollständiger Binärbaum. 2) Die Blätter der Tiefe n sind linksbündig im Baum angeordnet. 3) Knoten sind items. Der Schlüssel jedes Knotens ist größer als die Schlüssel seiner direkten Nachfolger (Söhne). G.Heyer 6 Algorithmen und Datenstrukturen Beispiel: 9 6 7 2 3 4 Heaps lassen sich einfach als Arrays realisieren: Knoten werden einfach von der Wurzel beginnend auf jeder Ebene von links nach rechts durchnumeriert. Knoten a[i] hat Söhne a[2i] und a[2i+1]. Heap-Bedingung: a[i].key > a[2i].key und a[i].key > a[2i+1].key maximales Element eines Heaps: Wurzel Idee für Sortieren: Heap für zu sortierende Elemente herstellen, maximales Element entfernen, Heap-Bedingung wiederherstellen usw. Wie macht man das? 1) Mache letztes Element e zur Wurzel 2) Vertausche e jeweils mit seinem größten Sohn, bis Heap-Bedingung erfüllt ist (lasse e versickern) G.Heyer 7 Algorithmen und Datenstrukturen versickere downheap ([a], N, k); int j, v; v= a[k]; while (k <= N/2) { j=k+k; if (j<N && a[j] < a[j+1]) j++; if (v >= a[j]) break; a[k] = a[j]; k= j; } a[k] = v; } G.Heyer 8 Algorithmen und Datenstrukturen Heapsort heapsort (int [a], int N) /*sortiert a[1] bis a[N] */ { int k, t; /*wandle a[1] bis a[N] in Heap um*/ for (k=N/2; k>=1; k--) downheap ([a], N, k); while (N>1) { /*vertausche a[1] und a[N] und laß a[1] versickern*/ t= a[1]; a[1]= a[N]; a[N] = t; downheap ([a], --N, 1); } } Worst case Komplexität: Aufruf von downheap erzeugt höchstens log N Vertauschungen. N/2 + N-1 mal aufgerufen, damit also O(N log N). Zusätzlicher Speicherplatz konstant, also echtes in situ (in place) Verfahren. G.Heyer 9 Algorithmen und Datenstrukturen BucketSort Unterbietet n log n im average case: O(n) Voraussetzung: Schlüssel kommen gleichverteilt in festem Intervall vor (hier benutztes Beispiel: Schlüssel aus 0..99) auf Kosten zusätzlichen Speicherplatzes O(n) Idee: Schlüsselintervall wird in n gleichgroße Teilintervalle aufgeteilt. Zusätzlich zu Array a[1..n] gibt es Array b[0..n-1] von Zeigern auf n lineare Listen (Buckets, Körbe). Die Listen enthalten die Elemente, die in dem jeweiligem Teilintervall liegen. G.Heyer 10 Algorithmen und Datenstrukturen for i:= 0 to n-1 do initialisiere b[i] mit leerer Liste for i:= 1 to n do trage a[i] in Liste b[a[i].key div 10] ein for i:= 0 to n-1 do sortiere Listen b[i] nach Standardverfahren füge Listen b[0], b[1], ... b[n-1] zu sortierter Liste zusammen Wahrscheinlichkeit ist sehr hoch, daß nur sehr kurze Listen entstehen, dadurch linearer average case. Worst case hängt von worst case für gewähltes Standardverfahren ab. G.Heyer 11 Algorithmen und Datenstrukturen Mergesort John von Neumann, 1945 Algorithmus Mergesort (F) Falls F leer oder einelementig -> Fertig. Sonst: Divide: Teile F in 2 möglichst gleichgroße Hälften F1, F2. Conquer: Sortiere L1 und L2 mittels Mergesort. Merge: Verschmelze die sortierten Teillisten zu sortierter Liste. Verschmelzen kann durch 2 Zeiger erfolgen, die die sortierten Teillisten durchwandern: Zeigen zunächst auf erstes Element, vergleichen Schlüssel, tragen kleineres item in konstruierte Liste ein und bewegen den Zeiger auf dieses Element um eine Position weiter. G.Heyer 12 Algorithmen und Datenstrukturen mergesort mergesort (int a[], int l, int r) /*sortiert a[l] bis a[r] nach aufsteigenden Schlüsseln*/ { int i, j, k, m; if (r>1) /*Folge hat mindestens 2 Elemente*/ { m= (r+l)/2; /*Mitte der Folge bestimmen*/ mergesort(a, l, m); mergesort(a, m+1, r); for (i=m+1; i>1; i--) b[i-1]= a[i-1]; for (j=m; j<r; j++) b[r+m-j]= a[j+1]; for (k=l;k<=r;k++) /*Zweiweg-Mischen*/ a[k]=(b[i]<b[j]) ? b[i++]: b[j--]; }} G.Heyer 13 Algorithmen und Datenstrukturen Komplexität: Beim Mischen werden Q(N) Schlüsselvergleiche gemacht. Rekursionstiefe logarithmisch beschränkt, insgesamt ergeben sich Q(N log N) Schlüsselvergleiche, denn C(N) = C(N/2) + C(N/2) + Q(N) = Q(N log N) Auch Anzahl der Bewegungen ist Q(N log N). nichtrekursive Varianten: Reines 2-Wege-Mergesort Es werden jeweils Teilfolgen der Länge 2, 4, 8 usw verschmolzen bis Folge sortiert ist. Dabei können kürzere Randstücke am rechten Rand übrigbleiben. G.Heyer 14 Algorithmen und Datenstrukturen Beispiel: 3|6|5|9|7|8|4|1|2|0 3 6|5 9|7 8|1 4|0 2 3 5 6 9|1 4 7 8|0 2 1 3 4 5 6 7 8 9|0 2 0 1 2 3 4 5 6 7 8 9 Komplexität wie originales Mergesort G.Heyer 15 Algorithmen und Datenstrukturen Natürliches 2-Wege-Mergesort Verschmelzprozeß wird nicht mit einelementigen Listen begonnen, sondern mit möglichst langen bereits sortierten Teilfolgen. Jeweils zwei benachbarte Teilfolgen werden verschmolzen. Beispiel: 3 6|5 7 9|1 8|0 2 4 3 5 6 7 9|0 1 2 4 8 0 1 2 3 4 5 6 7 8 9 Algorithmus nutzt Vorsortierung aus: falls Liste bereits sortiert, so wird das in O(N) Schritten festgestellt. G.Heyer 16 Algorithmen und Datenstrukturen Anmerkung: wie läßt sich Grad der Vorsortierung einer Folge F = k1,...,kn von Schlüsseln messen? Vorschlag 1: Zahl der Inversionen (Vertauschungen) von F inv(F) = |{(i,j) | 1 i < j n, ki > kj}| mißt so etwas wie Entfernungen zur richtigen Position Vorschlag 2: Anzahl der runs, d.h. der vorsortierten Teillisten (siehe oben) runs(F) = |{(i) | 1 i < n, ki+1 < ki}| + 1 Vorschlag 3: Länge der längsten sortierten Teilliste, las(F), bzw. rem(F) = n - las(F) (damit wie oben kleiner besser ist) G.Heyer 17 Algorithmen und Datenstrukturen Beispiele: F: 3 6 5 7 9 1 8 0 2 4 1 0 3 2 5 4 7 6 9 8 inv(F): 3+5+4+4+5+1+3+0+0+0 = 25 1+0+1+0+1+0+1+0+1+0 = 5 runs(F): 4 3 6|5 7 9|1 8|0 2 4 6 1|0 3|2 5|4 7|6 9|8 rem(F): 10 - 3 = 7 10 - 2 = 8 Es gilt: 0 inv(F) n(n-1)/2 1 runs(F) n 0 rem(F) n-1 G.Heyer 18 Algorithmen und Datenstrukturen Zusammenfassung Sortierverfahren best case average case worst case zus. Speicher Auswahl n n2 n2 1 Einfügen n n2 n2 1 Bubblesort n n2 n2 1 n2 log n Quicksort n log n n log n Heapsort n log n n log n Bucketsort Mergesort G.Heyer n n log n n n log n 19 n log n n log n, n2 n log n 1 n n Algorithmen und Datenstrukturen