Adnan Kadric Kevin Kandler Seminararbeit Sommersemester 2017

Ähnliche Dokumente
Alle bislang betrachteten Sortieralgorithmen hatten (worst-case) Laufzeit Ω(nlog(n)).

Sortieralgorithmen. Jan Pöschko. 18. Januar Problemstellung Definition Warum Sortieren?... 2

Randomisierte Algorithmen 2. Erste Beispiele

Entscheidungsbäume. Definition Entscheidungsbaum. Frage: Gibt es einen Sortieralgorithmus mit o(n log n) Vergleichen?

Kapitel 6 Elementare Sortieralgorithmen

Sortierverfahren für Felder (Listen)

Abgabe: (vor der Vorlesung) Aufgabe 2.1 (P) O-Notation Beweisen Sie die folgenden Aussagen für positive Funktionen f und g:

1. Musterlösung. Problem 1: Average-case-Laufzeit vs. Worst-case-Laufzeit

Datenstrukturen & Algorithmen

2 Sortieren. Beispiel: Es seien n = 8 und a = i : a i : ϕ(i) : a ϕ(i) :

Datenstrukturen und Algorithmen

Algorithmen und Datenstrukturen 1

Algorithmen und Datenstrukturen Wintersemester 2004/ November T(n) = T(n a) + T(a) + n

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6

Folge 13 - Quicksort

Algorithmen und Datenstrukturen SoSe 2008 in Trier. Henning Fernau Universität Trier

Algorithmen und Datenstrukturen

Kostenmodell. Daniel Graf, Tobias Pröger. 22. September 2016 (aktualisierte Fassung 5 vom 9. Oktober 2016)

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / 2015 Vorlesung 3, Donnerstag 6.

Übersicht. Datenstrukturen und Algorithmen. Übersicht. Divide-and-Conquer. Vorlesung 9: Quicksort (K7)

Übungsblatt 1. f(n) = f(n) = O(g(n)) g(n) = O(f(n)) Zeigen oder widerlegen Sie: 3 n = Θ(2 n ) Aufgabe 1.2 Gegeben sei die folgende Funktion:

Übungsblatt 2 - Lösung

12 (2-4)-Bäume Implementierbare Funktionen. (2-4)-Bäume sind durch folgende Eigenschaften deniert: 1. Alle Äste sind gleich lang

Abschnitt: Algorithmendesign und Laufzeitanalyse

Binary Decision Diagrams (Einführung)

Technische Universität Wien Institut für Computergraphik und Algorithmen Arbeitsbereich für Algorithmen und Datenstrukturen

Programmiertechnik II

T (n) = max. g(x)=n t(n) S(n) = max. g(x)=n s(n)

Programmieren I. Kapitel 7. Sortieren und Suchen

5 Zwei spieltheoretische Aspekte

Mathematik II für Studierende der Informatik. Wirtschaftsinformatik (Analysis und lineare Algebra) im Sommersemester 2016

Grundlagen der Programmierung 2. Sortierverfahren

Permutationen und symmetrische Gruppe

Pro Informatik 2009: Objektorientierte Programmierung Tag 17. Marco Block-Berlitz, Miao Wang Freie Universität Berlin, Institut für Informatik

Referat zum Thema Huffman-Codes

Klausur Algorithmen und Datenstrukturen

Name:... Vorname:... Matrikel-Nr.:... Unterschrift:...

3.2. Korrektheit und Komplexität am Beispiel: Sortieren Sortieren ist eine wichtige Basis-Operation für komplexe Algorithmen

Kapitel 3: Untere Schranken für algorithmische Probleme Gliederung

Übungsaufgaben: 1. Objektorientierte Programmierung - Teil 1

Übersicht. Datenstrukturen und Algorithmen Vorlesung 5: Rekursionsgleichungen (K4) Übersicht. Binäre Suche. Joost-Pieter Katoen. 20.

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Dynamisches Huffman-Verfahren

1. Grundlagen Sortieren Vertauschen Selektion Einfügen Quicksort Suchen...

Datenstrukturen und Algorithmen

Algorithmen und Datenstrukturen

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v)

Eine Baumstruktur sei folgendermaßen definiert. Eine Baumstruktur mit Grundtyp Element ist entweder

Übung zur Vorlesung Algorithmische Geometrie

Gruber I Neumann. Erfolg in VERA-8. Vergleichsarbeit Mathematik Klasse 8 Gymnasium

37 Gauß-Algorithmus und lineare Gleichungssysteme

13. Binäre Suchbäume

3. Musterlösung. Problem 1: Boruvka MST

Vorkurs: Mathematik für Informatiker

Einstieg in die Informatik mit Java

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Programmiertechnik II

Darstellungsformeln für die Lösung von parabolischen Differentialgleichungen

3.2 Binäre Suche. Usr/local/www/ifi/fk/menschen/schmid/folien/infovk.ppt 1

Untersuchen Sie, inwiefern sich die folgenden Funktionen für die Verwendung als Hashfunktion eignen. Begründen Sie Ihre Antwort.

4 Greedy-Algorithmen (gierige Algorithmen)

Datenstrukturen & Algorithmen Lösungen zu Blatt 6 FS 14

Vom Leichtesten zum Schwersten Sortieralgorithmen

Seminar über Algorithmen, SS2004. Textkompression. von Christian Grümme und Robert Hartmann

Dieses Quiz soll Ihnen helfen, Kapitel besser zu verstehen.

Binäre Bäume Darstellung und Traversierung

16. All Pairs Shortest Path (ASPS)

Ausarbeitung zum Modulabschluss. Graphentheorie. spannende Bäume, bewertete Graphen, optimale Bäume, Verbindungsprobleme

14. Rot-Schwarz-Bäume

JAVA - Suchen - Sortieren

2 i. i=0. und beweisen Sie mittels eines geeigneten Verfahrens die Korrektheit der geschlossenen Form.

Antwort: h = 5.70 bit Erklärung: Wahrscheinlichkeit p = 1/52, Informationsgehalt h = ld(1/p) => h = ld(52) = 5.70 bit

Kurs über Lineare Gleichungssysteme. PD Dr. Karin Halupczok

Effiziente Algorithmen und Datenstrukturen I. Kapitel 10: Lineare Algebra

2. Spezielle anwendungsrelevante Funktionen

2. Felder (Arrays) 2.1 Suchen in Feldern. lineares Suchen: siehe Kapitel 1. Binäres Suchen. Vor.: Elemente (z.b. aufsteigend) sortiert

TU Darmstadt FB Mathematik, AG 9 WS 2004/2005 Jakob Creutzig (1 + ρ)

Algorithmik WS 07/ Vorlesung, Andreas Jakoby Universität zu Lübeck

Algorithmen & Datenstrukturen 1. Klausur

Effiziente Algorithmen

damit hätten wir nach Ende der Schleife: "a[0 n-1] enthält nur Elemente aus a[0 n-1], aber in sortierter Reihenfolge".

Die (Un-)Sicherheit von DES

31 Polynomringe Motivation Definition: Polynomringe

Informatik II. Sommersemester 2011 IV/X/MMXI, Name:... Matrikelnummer:...

Inhaltsverzeichnis. Einführende Bemerkungen 11. Das Fach Informatik 11 Zielsetzung der Vorlesung Grundbegriffe

Lösungen zur Klausur GRUNDLAGEN DER WAHRSCHEINLICHKEITSTHEORIE UND STATISTIK

Unabhängigkeit KAPITEL 4

Grundlegende Sortieralgorithmen

3. Das Reinforcement Lernproblem

Komplexität von Algorithmen

In diesem Abschnitt betrachten wir nur quadratische Matrizen mit Komponenten aus einem Körper K, also A K n n für ein n N. Wenn (mit einem n > 1)

Klausur Informatik B April Teil I: Informatik 3

1 Zahlentheorie. 1.1 Kongruenzen

WS 2009/10. Diskrete Strukturen

k np g(n, p) = Pr p [T K] = Pr p [T k] Φ. np(1 p) DWT 4.1 Einführung 359/467 Ernst W. Mayr

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2

Klausur zur Vorlesung,,Algorithmische Mathematik II

Stochastik I. Vorlesungsmitschrift

Technische Informatik - Eine Einführung

Transkript:

Adnan Kadric 56821 Kevin Kandler 57274 Seminararbeit Sommersemester 2017 1

Contents 1 Einleitung 3 1.1 Sortieren in Linearer Zeit.................... 3 1.1.1 Untere Schranke für das Sortieren........... 3 1.1.2 Das Entscheidungsbaum-Modell............ 4 1.1.3 Eine untere Grenze für den schlechtesten Fall..... 5 1.1.4 Beweis........................... 5 2 Countingsort 6 2.1 Zeit von Countingsort...................... 8 3 Radixsort 9 3.1 Lochkarten............................ 9 3.2 Radixsort............................. 10 3.3 Code von Radixsort....................... 11 3.4 Lemma 1.3............................ 11 3.5 Lemma 1.4............................ 12 4 Bucketsort 13 4.1 Laufzeit Bucketsort........................ 14 5 Literatur 18 2

1 Einleitung Es existieren Sortier-Algorithmen, die n Zahlen in Zeit O(n log n) sortieren können. Darunter befinden sich Heapsort und Mergesort, die diese obere Grenze im schlechtesten Fall erreichen, während Quicksort dies im Mittel schafft. Für jeden der genannten Algorithmen kann eine Folge von n Eingabezahlen angegeben werden, für die der Algorithmus in der Zeit Ω(n log n)läuft. Eine interessante Eigenschaft weisen all diese Algorithmen auf: Die sortierte Reihenfolge, die sie bestimmen, basiert nur auf Vergleichen zwischen den Eingabeelementen. Daher werden diese Algorithmen auch vergleichende Sortierverfahren genannt. Die oben genannten Sortierverfahren gehören dieser Klasse an. Im nachfolgenden Abschnitt 1.1 wird bewiesen, dass im schlechtesten Fall jedes der vergleichenden Sortierverfahren Ω(n log n) Vergleichsoperationen durchführen muss, um n Elemente zu sortieren. Das bedeutet, dass Heapsort und Mergesort asymptotisch optimal sind. Dabei existieren keine anderen vergleichende Sortierverfahren, die um mehr als einen konstanten Faktor schneller sind. In Abschnitt 2, 3 und 4 werden 3 weitere Sortieralgorithmen - Countingsort, Radixsort und Bucketsort - vorgestellt, die alle in linearer Zeit sortieren. Diese Algorithmen benutzen noch andere Operationen als Vergleich, um die sortierte Reihenfolge zu bestimmen. Folglich gilt für sie die untere Grenze Ω(n log n) nicht. 1.1 Sortieren in Linearer Zeit 1.1.1 Untere Schranke für das Sortieren Bei vergleichenden Sortierverfahren kommen ausschließlich Vergleiche zwischen den Elementen vor, um Information über die Reihenfolge der Eingabesequenz (a 1, a 2,..., a n ) zu gewinnen. Für zwei gegebene Elemente a i und a j werden für die Bestimmung der relativen Reihenfolge einer der Tests a i < a j, a i a j, a i = a j,a i a j oder a i > a j vorgenommen. Es ist nicht möglich, die Werte der Elemente zu inspizieren oder auf anderem Weg Information über sie zu erlangen. Für die folgende Diskussion werden Elemente angenommen, die paarweise verschieden sind. Unter dieser Voraussetzung sind Vergleiche der Form a i = a j nutzlos. Daraus folgt, dass Vergleiche dieser Art nicht ausgeführt werden. Außerdem wird festgestellt, dass die Vergleichsoperationen a i a j, a i a j,a i > a j und a i < a j äquivalent sind, da sie zu identischen Informationen über die Reihenfolge von a i und a j führen. Das bedeutet schlussendlich, dass alle Vergleiche von der Art a i a j sind. 3

1.1.2 Das Entscheidungsbaum-Modell Sortierverfahren können durch abstrakte Entscheidungsbäume dargestellt werden. Ein Entscheidungsbaum ist ein vollständiger binärer Baum, der die Vergleiche zwischen den Elementen eines vorgegebenen Eingabefeldes darstellt. Alle anderen Aspekte wie Steuerung oder Datenbewegung werden vernachlässigt. Somit zeigt der Baum, welche Operationen auf welche Elemente des Eingabefeldes einer vorgegebenen Länge durchgeführt werden. Abbildung 1.1 zeigt den Entscheidungsbaum für Insertion Sort bei der Eingabe von drei Elementen. Abbildung 1.1 Entscheidungsbaum für Insertionsort von drei Elementen. Ein mit i:j gekennzeichneter innerer Knoten stellt einen Vergleich zwischen a i und a j dar. Ein Endknoten (Blattknoten) stellt die Permutation (π(1),...., π(n)) der Eingabeelemente dar und gibt die Reihenfolge a π (1) a π (2)... a π (n) an. Der schattierte Pfad zeigt die Entscheidungen die bei der Eingabefolge (a 1 = 6, a 2 = 8, a 3 = 5) getroffen werden. Die Permutation(3,1,2) am Blattknoten dieses Pfades sagt, dass die sortierte Reihenfolge a 3 = 5 a 1 = 6 a 2 = 8 ist. Es gibt somit 3!=6 mögliche Permutationen der Eingabeelemente und so hat der Entscheidungsbaum mindestens 6 Blätter. In einem Entscheidungsbaum wird jeder interne Knoten durch i:j dargestellt, für ein i und j aus dem Bereich 1 i, j n, wobei n die Anzahl der Elemente in der Eingabefolge angibt. Jeder Blattknoten steht für eine Permutation (π(1),..., π(n)) der Eingabeelemente. Die Ausführung des Sortieralgorithmus entspricht der Verfolgung eines einfachen Pfades von der Wurzel bis hinunter zum Blattknoten. Jeder interne Knoten symbolisiert einen Ver- 4

gleich der Art a i a j. Führt der Vergleich zu einem positivem Ergebnis, so wird der linke Teilbaum beschritten, andernfalls der rechte. Dieses Szenario gilt für alle Knoten eines Entscheidungsbaumes. Bei Erreichen eines Blattknotens hat der Sortieralgorithmus die Reihenfolge a π (1)... a π (n) und damit sein Ziel festgelegt. Da jeder korrekt arbeitende Sortieralgorithmus in der Lage sein muss jede Permutation der Eingabe zu erzeugen, muss jede der n! Permutationen als einer der Blattknoten im Entscheidungsbaum vorkommen. Darüber hinaus muss jeder Blattknoten von einem von der Wurzel startenden Pfad erreichbar sein, der einer tatsächlichen Ausführung des vergleichenden Sortierverfahrens entspricht. Folglich werden nur solche Entscheidungsbäume betrachtet, in denen jede Permutation als erreichbarer Blattknoten erscheint. 1.1.3 Eine untere Grenze für den schlechtesten Fall Die Länge des längsten Pfades von der Wurzel eines Entscheidungsbaumes zu den erreichbaren Blattknoten stellt die Anzahl von Vergleichen dar, die im schlechtesten Fall vom Sortieralgorithmus ausgeführt werden. Folglich entspricht die Anzahl von Vergleichen eines vergleichenden Sortieralgorithmus im schlechtesten Fall der Höhe des Entscheidungsbaumes. Eine untere Grenze für die Höhe aller Entscheidungsbäume, in der jede Permutation als ein erreichbarer Blattknoten erscheint, ist folglich eine untere Grenze für die Laufzeit irgendeines vergleichenden Sortieralgorithmus 1.1.4 Beweis Theorem 1.1. Jeder vergleichende Sortieralgorithmus erfordert im schlechtesten Fall Ω(n log n) Vergleichsoperationen. Nach der vorangegangenen Diskussion genügt es, die Höhe eines Entscheidungsbaumes zu bestimmen, in dem jede Permutation als erreichbarer Blattknoten vorkommt. Betrachte einen Entscheidungsbaum der Höhe h mit l erreichbaren Blattknoten, der für ein vergleichendes Sortierverfahren angewandt auf n Elemente steht. Da jede der n! Permutationen der Eingabefolge als Blattknoten vorkommt, gilt n! l. Da ein binärer Baum der Höhe h nicht mehr als 2 h Blattknoten hat, gilt: n! l 2 h sodass durch Anwenden des Logarithmus die Aussage folgt: h lg(n!) = Ω(n lg n) 5

Korollar 1.1. Heapsort und Mergesort sind asymptotisch optimale vergleichende Sortierverfahren. beweis 1.1. Die obere Grenze O(n lg n) der Laufzeiten von Heapsort und Mergesort entspricht der unteren Grenze im schlechtesten Fall von Theorem 1.1. 2 Countingsort Der Countingsort setzt für jedes Eingabeelement n voraus, dass n N 0 ist. Die Variable k nimmt den größten Wert des Eingabefeldes an. Der Algorithmus bestimmt für jede eingegebene Zahl n die Anzahl der Elemente, die kleiner sind als n. Somit wird die Position ermittelt in dem n später stehen muss. Bsp 2.1: Auf das Eingabefeld A = [2, 1, 3, 5, 7] soll ein neuer Eingabewert n = 18 eingefügt werden. n gehört im Eingabefeld an die Stelle A[5]. Hier ist zu beachten, dass man in Feldern mit der Zahl 0 beginnt zu zählen. Somit wird k = 18 dadurch das der neue Wert betragsmäßig größer ist als alle anderen Werte im Feld. Zur Optimierung des Algorithmus wird im Eingabefeld mit der Zahl 1 begonnen zu zählen und nicht wie im bsp 2.1 mit der Zahl 0. Dies hat den Vorteil, dass der Algorithmus merkt das 5 Elemente kleiner gleich n sind und somit n an stelle A[6] kommt. Dadurch wird der Vorteil gewonnen das nun das Eingabefeld A die Größe A.länge besitzt. Das erlaubt es dem Algorithmus mit den Indexwerten der Felder zu arbeiten und nicht, wie man naiv vermuten würde mit Vergleichen. Somit wird der Code für den Sortieralgorithmus so programmiert, dass die Eingabe aus einem Feld A = [1... n] und die Länge von A gleich der Anzahl der Eingabeelemente gleich n ist. Zum Code werden außerdem noch zwei weitere Felder benötigt. Ein Feld B das die sortierte Ausgabe speichert. Mit der Eigenschaft, dass dieses Feld die gleiche grösse hat wie A. Ebenso wird auch ein Hilfsfeld C benötigt was einen temporären Arbeitsspeicher darstellen soll. Dieses Feld zählt wie oft ein Wert in A vorkommt und wie viele Werte kleiner sind als A[i], i (1,..., A.Länge). Anders als bei den Ein- und Ausgabefeld beginnt das Hilfsfeld mit dem Wert 0 zu zählen und hat die Länge k. Im Bsp 2.1 wäre k = 18 und somit wäre C[0...18] und C.Länge = 19. 6

Abbildung 2.1 Abbildung 2.1 zeigt die Arbeitsweise von Countingsort auf das Eingabefeld A[1..8], alle Elemente des Feldes sind positive Zahlen die 5 sind. (a) Das Feld A und das Hilfsfeld C nach Ausführung von Zeile 5. Das bedeutet, dass in C steht wie oft jeder Wert in A vorkommt.(b) Das Feld C nach Zeile 8. Jetzt kennt C durch Aussumieren über A n n+1 + A n n+2 +... + A n alle Werte die kleiner sind als i. (c)-(e) Das Ausgabefeld B und das Hilfsfeld C nach drei Iterationen der Schleife aus den Zeilen 10-12. Nur die schattierten Elemente des Feldes B wurden eingeführt. (f) Das abschließende sortierte Ausgabefeld B. Abbildung 2.2 Abbildung 2.2 gibt die Arbeitsweise des Countingssorts wieder. Die for- Schleife in Zeile 2 und 3 setzt jedes Element von C auf 0. Danach folgt die Schleife in 4 und 5. Hier arbeitet der Code mit der Laufvariable j = 1 und geht bis zur Größe von A. Mit dieser Schleife inkrementiert dieser dann im 7

Feld C den Wert von A[j] an der Position C[A[j]]. Somit erhalten wir wie oft der Wert in unserem Eingabef eld vorkommt. In den Zeilen 7-8 bekommt man durch aufsummieren wie viele Elemente kleiner als i sind. Hier ist zu beachten, dass das Feld C bei der 0 anfängt zu zählen. In der letzten Schleife platziert der Algorithmus jedes Element von A[j] an der richtigen Stelle im Ausgabefeld. Sollten alle Eingabeelemente paarweise verschieden sein, werden diese beim erstmaligen ausführen von Zeile 10 für jedes A[j] der Wert C[A[j]] in dessen richtige Endposition im Ausgabefeld bestimmt. Wieso das so ist, ist leicht nachzuvollziehen. Dadurch, dass es C[A[j]] Elemente gibt die kleiner oder gleich A[j] sind, kann es nie anders auftreten. Der Algorithmus schließt nicht aus, dass die Elemente paarweise verschieden sein müssen deswegen wird im Code C[A[j]] jedes mal dekrementiert, wenn er einen Wert A[j] in das Ausgabefeld B schreiben muss. Das bewirkt, falls ein Wert A[j] geschrieben werden soll und der Gleiche Wert im Ausgabefeld schon vorhanden ist, dieser an die unmittelbar vorherige Position von A[j] geschrieben wird. 2.1 Zeit von Countingsort Welche Zeit benötigt der Algorithmus Die Schleife in Zeile 2-3 benötigt die Zeit Θ(k), die Schleife der Zeilen 4-5 läuft in Zeit Θ(n) und die Schleife in Zeile 7-8 braucht genauso wie die Schleife aus Zeile 2-3 Θ(k) Zeit. Die letzte wiederum braucht auch Θ(n). Daraus folgt, dass die Gesamtlaufzeit von Countingsort nur Θ(n + k) Zeit braucht. In der Praxis ist es erstrebenswert das k = O(n) ist. Dadurch das dann das Verfahren auch in Θ(n) Zeit läuft. Die bewiesene Untere Schranke aus Abschnitt 1.1 gilt hier nicht, da der Countingsort diese tatsächlich unterbietet, da es kein vergleichbares Sortierverfahren ist. Im Code kommen auch keine Vergleiche zwischen den Elementenvor. Stattdessen arbeitet dieses Sortierverfahren mit den reellen Werten der Elemnte als Index in einem Feld. Die untere Schranke von Ω(n lg n) gilt nicht, wenn Sortierverfahren betrachtet werden die nicht vergleichbar sind. Eine wichtige Eigenschaft des Countingsort ist, dass er stabil ist. Dadurch, dass die Zahlen mit gleichen Werten im Ausgabefeld in der gleichen Reihenfolge erscheinen, wie sie eingelesen wurden. Das beduetet sind zwei Zahlen gleich entscheidet der Algorithmus, dass die zuerst eingelesene Zahl aus dem Eingabefeld als erstes in das Ausgefeld geschrieben wird. Eigentlich ist die Stabilität nur von Bedeutung, wenn auch sogenannte Satellitendaten mit den zu sortierenden Elementen mitgeführt werden. Die Stabilität ist jedoch aus noch einem anderen Grund wichtig. Der Countingsort wird meist als Unteroutine von Radixsort verwendet. 8

3 Radixsort Dieser Algorithmus hatte seinen Höhepunkt zur Zeit der Lochkarten, wie diese die man heute nur noch in Museen findet. 3.1 Lochkarten Die Lochkarte war zur seiner damaligen Zeit essentiell was die Datenverarbeitung betraf. Sie diente als Eingabe und Speichermedium. Die Lochkarten haben insgesamt 80 Spalten und 12 Zeilen. Die Zeilen stellen die Dezimalzahlen von 0 bis einschließlich 9 dar. Die restlichen Zeilen dienen als Vorzeichen, sprich dem plus und dem minus. Die Spalten wiederum müssen nicht als eine Zahl gewertet werden sondern lassen sich aufteilen. So könnte ein Unternehmen, dass die Ware mit der Produktnummer Y an den Kunden X, zum Preis i,mit der Stückzahl Z verkauft, auswerten. Teilt man diese 80 Spalten durch vier, hätte jeder dieser Variablen 20 Spalten für sich. Da es jedoch unnötig ist dem Preis i 20 Spalten zuzuweisen, da der Preis in der Regel aus einigen vorkomma, und aus genau zwei nachkomma stellen, besteht. So teilt dieses Unternehmen für X = 30 Spalten, Y = 20, Z = 20 und i = 10, zu. Das Unternehmen erstellt jetzt einen Datensatz auf einer Lochkarte, auf einer der die Werte festgehalten werden. Bsp 3.1 Kunde Müller Kunden I D = 213 kauft das Produkt mit der Produktnummer=1457 zum Preis von 14 Euro und einer Stückzahl von 1000 Stück. Wie im Bsp 3.1 gezeigt wird hat der Kunde Müller die Kunden id von 213 das setzt voraus das es weitere Kunden gibt und zwar mindestens 212 weitere. Beim Radixsort bietet es sich an, wenn jeder Wert der ausgewertet werden soll die gleiche Größe hat. So würde der Kunde 3 und 212 schwer zu sortieren sein. Deswegen werden die freien Plätze der Lochkarte mit 0 Initalisiert. Dies bedeutet wenn von 30 stellen tatsächlich nur 3 stellen verwendet werden, werden die restlichen Spalten mit 0 Initialisiert. Angenommen das Unternehmen hat einem Tag nicht nur einen Kunden, sondern 1000, so kann jetzt der Tagesumsatz nach der Größe sortiert werden. Es wird jedoch verausgesetzt, dass die Daten von einer geeigneten Kartenlesemaschine auf einen Computer überspielt werden und dieser die Daten dann Verarbeiten kann, Voraussetzung ist hier eine entsprechenden Programmierung. Nicht nur Zahlen sondern auch Buchstaben und Sonderzeichen lassen sich auf einer Lochkarte kodieren. Ermöglicht wird das durch Merhfachlochungen innerhalb einer Spalte. 4096 verschiedene Zeichen sind mit 12 Löchern darstellbar. 9

3.2 Radixsort Für den weiteren Verlauf des Algorithmuses wird das Bsp 3.1 betrachtet. Jedoch werden die Kunden nach Kundennummer sortiert. Hier bietet sich der Radixsort gut an. Der Radixsort arbeitet in dem es jeweils eine Zahl aus allen Datensätzen vergleicht und diese dann sortiert.rein Inutitiv sollte man meinen, dass es sich anbietet Zahlen des Datensatzes mit dem Höchstwertigen Bit anzufangen zu vergleichen und dann zu Sortieren. Jedoch darf man hier nicht vergessen, dass der Algrithmus aus der Lochkarten Zeit stammt und diese Prozedur zu viele temporäre Stapel erzeugen würde. Entgegen der Intuition löst Radixsort das Problem indem es zuerst nach der Stelle mit der geringsten Wertigkeit sortiert. Daraufhin fügt dieser dann die Karten zu einem Kartenstapel zusammen, wobei die Karten aus dem Kasten 0 vor denen des Kasten 1 kommen, dieser wiederum vor denen aus Kasten 2 und so weiter. Ist dies für die geringste Wertigkeit abgeschlossen beginnt der Algorithmus mit der zweitgeringsten Wertigkeit und fügt sie auf die gleiche Art und weise wieder zusammen. Dies wird fortgeführt bis die Karten nach allen 30 Stellen sortiert wurden. Bemerkenswerter weise sind die Karten zu diesem Zeitpunkt vollständig nach der 30-stelligen Zahl sortiert. Somit werden zum Sortieren nur 30 durchläufe durch den Kartenstapel gebraucht. Bsp radix sort. Abbildung 3.1 Damit der Radixsort korrekt sortieren kann, muss das Verfahren zum Sortieren nach einer Stelle stabil sein. Das Sortierverfahren ist auch Stabil, jedoch muss der Operator darauf achten, dass die Reihenfolge der Lochkarten in der sie aus dem Kasten kommen nicht verändert werden. Auch nicht dann 10

wenn alle Lochkarten eines Kastens in der gewählten Spalte die gleiche Ziffer stehen haben. Bsp 3.2 Ein Beispiel aus heutiger Zeit ohne Lochkarten. Radixsort wendet man an, um Datensätze zu sortieren, die aus mehreren Komponenten-Schlüssel bestehen wie ein Datum. Bei einem Datum gibt es drei Schlüssel: der Tag, der Monat und das Jahr. Als erstes wird nach dem Jahr Sortiert sollten diese übereinstimmen, dann nach Monat und dann gegebenenfalls nach dem Tag. 3.3 Code von Radixsort Der Code für Radixsort ist einfach. Der Algorithmus setzt voraus das jedes Element des Feldes aus einer d stelligen Zahl besteht wobei die Stelle 1 die niederwertigste Stelle ist und die Stelle d die höchstwertigste. Im Zusammenspiel mit Countingsort wird auch vorausgesetzt, dass die Zahlen ganze Positive Zahlen sind. Abbildung 3.2: Code von Radixsort 3.4 Lemma 1.3 Sind n d-stellige Zahlen gegeben, bei denen jede Stelle k mögliche Werte annehmen kann, sortiert Radixsort diese Zahlen in der Zeit Θ(d(n + k)), wenn das in den Zwischenschritten verwendete stabile Sortierverfahren jeweils Zeit Θ(n + k) benötigt. Beweis: Die Richtigkeit von Radixsort erfolgt durch Induktion. Die Analyse der Laufzeit hängt von dem im Zwischenschritt verwendeten stabilen Sortierverfahren ab. Wenn jede Stelle im Bereich von 0 bis k 1 liegt, sodass sie k mögliche Werte annehmen kann und k nicht zu groß ist, dann ist Countingsort die naheliegende Wahl. Jeder Durchlauf über die n d-stellige Zahlen benötigt dabei die Zeit θ(n+k). Es gibt somit d Durchläufe und die gesamte 11

Laufzeit für Radixsort θ(d(n + k)). Für konstantes d und k = O(n) läuft Radixsort in Linearer Zeit. 3.5 Lemma 1.4 Bei gegebenen n b-bit Zahlen und einer positiven Zahl r b sortiert Radixsort diese Zahlen in der Zeit von Θ((b/r)(n + 2 r ), wenn das verwendete stabile Sortierverfahren für die Zahlen im Bereich von 0 bis k die Zeit Θ(n + k) benötigt. Beweis: Für einen Wert r b wird jeder Schlüssel in d = b/r Stellen von r Bits unterteilt. Jede Stelle kann als eine Zahl im Bereich von 0 bis 2 r 1 betrachtet werden, mit dem Effekt, dass der Countingsort mit k = 2 r zur Anwendung kommt. Unterteilt man z.b. ein 32-Bit Wort in 4 Stellen zu jeweils 8 Bits, dann ist b = 32, r = 8, k = 2 r = 256 und d = b/r = 4. Jeder Durchlauf des Countingsort benötigt also Θ(n + k) = θ(n + 2 r ) Zeit. Es sind d Durchläufe notwendig, mit einer Gesamtlaufzeit von θ(d(n + 2 r )) = θ((b/r)/(n + 2 r )). Sind Werte für n und b gegeben, dann kann der Wert von r, unter Berücksichtigung von r b, dahingehend gewählt werden, dass der Ausdruck (b/r)(n + 2 r ) minimiert wird. Ist b < lg n, dann gilt für jeden Wert r b die Gleichung (n + 2 r ) = θ(n). Wird r = b gewählt, dann ergibt sich eine Laufzeit von (b/b)(n/ + 2 b ) = θ(n), was asymptotisch optimal ist. Ist b lg n, dann wird mit der Wahl r = lg n die, bis auf eine Konstante, beste Laufzeit erreicht. Mit der Wahl von r = lg n beträgt die Laufzeit θ(bn/ lg n). Ist der Wert von r, wie oben angegeben, größer als lg n, dann wächst der 2 r Term im Zähler schneller als der r Term im Nenner; das führt zu einer Laufzeit von Ω(bn/ lg n). Ist der Wert von r dagegen kleiner als lg n, dann wächst der Term b/r und der Term n + 2 r bleibt bei Θ(n). Die Frage lautet also: Ist Radixsort einem vergleichenden Sortieralgorithmus, wie z.b. Quicksort, vorzuziehen? Angenommen b = O(lg n), was oft der Fall ist, und r lg n, dann beträgt die Laufzeit von Radixsort Θ(n). Im ersten Augenblick erscheint dies besser zu sein als die Laufzeit von Quicksort mit Θ(n lg n). Jedoch unterscheiden sich die konstanten, verborgenen Faktoren in der Θ Notation. Obwohl Radixsort eventuell weniger Durchläufe als Quicksort für die n Schlüssel benötigt, ist es vorstellbar, dass ein Durchlauf bei Radixsort eine signifikant längere Zeit braucht. Welcher Sortieralgorithmus nun vorzuziehen ist, hängt in erster Linie von den Eigenschaften der Implementierung ab, von der zugrunde liegenden Maschine (Quicksort ist bei der Nutzung von Hardware Caches oft effektiver als Radixsort) und von der Eingabe ab. Darüber hinaus sortiert die Version von Radixsort, die zwischendurch Countingsort verwendet, nicht in-place, was aber die Mehrheit 12

der vergleichenden Sortieralgorithmen mit einer Laufzeit von Θ(n lg n) tun. Folglich ist unter der Prämisse, dass primärer Speicher in ausreichender Zahl zur Verfügung steht, ein in-place Sortieralgorithmus wie Quicksort die erste Wahl. 4 Bucketsort Der Bucketsort unterliegt der Eigenschaft das die Eingabe unter der Gleichverteilung auftritt und hat eine mittlere Laufzeit von O(n). Bucketsort und der Countingsort sind schnell da sie gewisse Annahmen über die Eingabe treffen. Während der Countingsort vorgibt, dass die Eingabe positive ganze Zahlen aus einem kleinen Bereich sein müssen, geht Bucketsort davon aus, dass die Eingabe durch zufällige Prozesse erzeugt wird. Dieser Prozess verteilt die Eingabe gleichmäßig und unabhängig voneinander über den Zahlenbereich [0, 1) d.h die Eingabe darf nur von einschließlich 0 bis zur 1 gehen ohne die 1 selbst. Der Algrithmus teilt das Interval [0, 1) in Buckets auf, diese Intervalle sind gleichgroß, daraufhin verteilt er die n Eingabezahlen in diesem Bereich. Sind die Eingabezahlen gleichmäßig und unabhängig von einander verteilt ist nicht zu erwarten das viele Zahlen in die gleichen Buckets einsortiert werden. Um eine Ausgabe zu erzeugen werden die Zahlen innerhalb des Buckets sortiert und der Reihe nach ausgegeben. Der Code für den Bucketsort setzt voraus das die Eingabe ein Feld A mit der Größe n ist und jedes Element A[i] die Bedingung 0 a[i] < 1 erfüllt. Wie auch beim Countingsort wird hier ein Hilfsfeld benötigt mit der Größe b = [0... n 1]. Da dieser Algorithmus mit verketteten Listen (die Buckets) arbeitet, brauchen wir n solcher Hilfsfelder. Im Pseudocode wird davon ausgegangen das eine Verwaltung solcher Felder schon vorhanden ist (siehe code 8-9) 13

Abbildung 4.1: Code Bucketsort Abbildung 4.2 Um zu verstehen wie dieser Algorithmus arbeitet betrachtet man zwei Elemente A[i] und A[j]. unter der Annahme, ohne Beschränkung auf die Allgemeinheit, das A[i] A[j] ist. Wegen na[i] na[j] wird A[i] entweder in die gleiche Liste (Bucket) wie A[j] sortiert oder in eines mit einem kleinerem Index. Sollten A[i] und A[j] in das gleiche Bucket einsortiert werden, sorgt die for Schleife in zeile 7-8 dafür, dass diese in die richtige Reihenfolge kommen. Sollten diese Elemente in unterschiedliche Buckets kommen, dann sorgt die Schleife in Zeile 9 dafür, dass diese richtig sortiert werden. Somit arbeitet Bucketsort korrekt. 4.1 Laufzeit Bucketsort Um die Laufzeit auszuwerten, stellt man fest, dass alle Zeilen außer Zeile 8 im schlechtesten Fall die Zeit O(n) benötigt. Dabei legt man die Zeit fest, die durch die n Aufrufe von Sortieren durch Einfügen in Zeile 8 verbraucht wird. Um die Kosten für die Aufrufe von Sortieren durch Einfügen zu untersuchen, 14

führt man die Zufallsvariable n i ein, die die Anzahl der Elemente in Bucket B[i] beschreibt. Das Sortieren durch Einfügen in quadratischer Zeit läuft, ist die Laufzeit von Bucketsort n 1 T (n) = Θ(n) + O(n 2 i ). Nun bestimmt man die Laufzeit im Mittel von Bucketsort, indem die erwartete Höhe der Laufzeit berechnet wird und die Eingangsverteilung zu Grunde gelegt wird. Auf beiden Seiten wird ein Erwartungswert gebildet und dabei dessen Linearität ausgenutzt, so erhält man i=0 n 1 E[T (n)] = E[θ(n) + O(n 2 i )] i=0 n 1 = θ(n) + E[O(n 2 i )] wegen der Liniarität des Erwartungswertes i=0 n 1 = θ(n) + O(E[n 2 i ]) i=0 Wir behaupten, dass E[n 2 i ] = 2 1/n für i = 0, 1,..., n 1 gilt. Es überrascht nicht, dass jedes Bucket i für (E[n 2 i ]) den gleichen Wert hat, denn jeder Wert des Eingabefeldes A hat für jedes Bucket die gleiche Wahrscheinlichkeit, um in dieses eingefügt zu werden. Um die Gleichung E[n 2 i ] = 2 1/n zu beweisen, definieren wir die Indikatorfunktionen X ij = I{A[j] wird in Bucket i eingefügt} für i = 0, 1,..., n 1 und j = 1, 2,..., n. somit gilt n i = n j=1 X ij. Um (E[n 2 i ]) zu berechnen, multiplizieren wir das Quadrat aus und ordnen die Terme um: 15

(E[n 2 i ]) = n E j=1 n = E X ij j=1 k=1 2 n X ij X ik n = E Xi 2 j + = j=1 1 j n n E[Xi 2 j] + j=1 1 j n 1 i m k j 1 i m k j X ij X ik E[X ij X ik ] Die letzte Zeile folgt aus der Linearität des Erwartungswertes. Wir werten die beiden Summen seperat aus. Die Indikatorfunktion X ij ist mit einer Wahrscheinlichkeit 1/n gleich 1 und mit einer Wahrscheinlichkeit 1 1/n gleich 0; also gilt: (E[Xi 2 j]) = 1 2 1 ( n + 02 1 1 ) n = 1 n für k j sind die Variablen X ij und X ik unabhängig, sodass (E[X ij X ij ]) = E[X ij ] E[X ik ] = 1 n 1 n = 1 n 2 16

gilt. Substituieren wir diese beiden Erwartungswerte in die Gleichung, so erhalten wir (E[n 2 i ] = j=1 1 n + 1 j n 1 k n k j = n 1 n + n(n 1) 1 n 2 = 1 + n 1 n = 2 1 n 1 n 2 womit die Gleichung bewiesen ist. Setzen wir diese Erwartungswerte in die Gleichung ein, so sehen wir, dass die Laufzeit von Bucketsort im Mittel in Θ(n) + O(2 1/n) = θ(n) ist. Selbst wenn die Eingabefolge nicht einer gleichmäßigen Verteilung genügt, kann Bucketsort in linearer laufzeit laufen. Solange die Eigenschaft erfüllt ist, dass die Summe der Quadrate der Bucketgrößsen linear in der Gesamtzahl der Elemente ist, sagt uns die erste Gleichung, dass Bucketsort in linearer Zeit laufen wird. 17

5 Literatur Thomas H.Cormen. Introduction to Algorithms. Third Edition. July2009 1 1 Alle Bilder und Beweise in dieser Arbeit wurden aus diesem Buch übernommen 18