Title: Kapitel 7. Sortier-Algorithmen
1Kapitel 7. Sortier-Algorithmen
Vorbemerkungen Sortierproblem Gegeben Folge
von Datensätzen (items) s1, s2, ... sn Jedes si
besitzt Schlüssel ki (meist vom Typ
integer). Gesucht Permutation p, so daß kp(1)?
kp(2) ? ... ? kp(n) Interne Sortierverfahren
alle Datensätze im Hauptspeicher, sonst Nutzung
des Externspeichers Maße für die Laufzeit
Anzahl der Schlüsselvergleiche C (Comparisons)
und Anzahl der Zuweisungen von Datensätzen M
(Moves). C min, C max, C mit jeweils M min, M
max, M mit minimale, maximale, mittlere Anzahl
2Klassifizierung von Sortiertechniken
Sortieren durch 1. Auswählen 2. Einfügen 3.
Austauschen 4. Mischen 5. Streuen und Sammeln 6.
Fachverteilen
3Sortieren durch Auswahl (Selection Sort)
Methode Finde zuerst das kleinste Element im
Feld und tausche es gegen das an erster Stelle
befindliche Element aus, finde danach das
zweitkleinste Element und tausche es gegen das an
zweiter Stelle befindliche Element aus und fahre
in dieser Weise fort bis das gesamte Feld
sortiert ist. Für jedes i von 1,..., N-1
tauscht es ai gegen das kleinste Element in
ai , ... , aN aus (Im folgenden ist ai
immer der Wert des Schlüssels des i-ten
Feldelementes. )
4Funktion Selection_Sort
void selection_sort(int a , int N )
int i, j, min, t for ( i 1 i lt N i
) min i for ( j i1 j lt N j
) if ( a j lt a min ) min j t
a min a min a i a i
t Analyse Anzahl Schlüsselvergleiche S
i N(N-1) / 2 Q(N2) Anzahl Bewegungen von
Sätzen 3(N-1)
5Insertion Sort (Sortieren durch (direktes )
Einfügen)
(Beispiel Einsortieren der Karten beim
Kartenspiel) Methode Betrachte die Elemente
eines nach dem anderen und füge jedes an seinen
richtigen Platz zwischen den bereits betrachteten
ein (wobei diese sortiert bleiben). Das gerade
betrachtete Element wird eingefügt, indem die
größeren Elemente einfach um eine Position nach
rechts bewegt werden und das Element dann auf dem
frei gewordenen Platz eingefügt wird. Für jedes
i von 2 bis N werden die Elemente a 1
,..., a i sortiert, indem a i an die
entsprechende Stelle in der sortierten Liste von
Elementen in a1 ,..., ai-1 gesetzt wird.
6Funktion Insertion_Sort
void insertion_sort(int a , int p , int N
) int i, j, v for ( i 2 i lt N i
) v a i j i while ( a
j-1 gt v ) a j a j-1 j--
a j v / Programm läuft nur,
wenn jgt1/
7Sortieren von Dateien mit großen Datensätzen
Ziel Jedes Sortierverfahren so einzurichten,
dass es nur N Austauschoperationen von
vollständigen Datensätzen ausführt, indem man den
Algorithmus indirekt (unter Verwendung eines
Feldes von Indizes) mit der Datei arbeiten und
das Umordnen dann nachträglich vornehmen
lässt. Insbesondere, wenn das Feld a 1 , ...
, a N aus umfangreichen Datensätzen besteht,
zieht man es vor, mit einem Indexfeld p 1 ,
... , p N zu arbeiten, wobei ein Zugriff auf
das Originalfeld nur für Vergleiche erfolgt. In
C ist es zweckmäßig, eine auf dem gleichen
Prinzip beruhende Implementierung zu entwickeln,
die ein Feld von Maschinenadressen (Zeigern)
verwendet.
8Beispiel Umordnen eines sortierten Feldes
Vor dem Sortieren
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
k a k p k
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
Nach dem Sortieren
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
k a k p k
1 11 9 15 8 6 14 12 7 3
13 4 2 5 10
Nach dem Permutieren
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
k a k p k
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15
9Insertion sort unter Hinzufügung eines
Indexfeldes
insertion ( int a , int p , int N )
int i, j, v for ( i 0 i lt N i
) p i i for ( i 2 i lt N i
) v p i j i while ( a
p j - 1 gt a v ) p j p j - 1
j--
10Funktion zum Umordnen einer Datei
insitu ( int a , int p , int N )
int i , j , k , t for ( i 1 i lt N
i ) if ( p i ! i ) t
a i k i do j k a
j a p j k p j p j
j while ( k ! i ) a j
t
11Insertion sort unter Verwendung eines Feldes
von Zeigern
insertion ( int a , int p , int N)
int i, j, v for (i 0 i lt N i
) p i a i for (i 2 i lt N
i ) v p i j i while (
p j -1 gt v ) p j p j - 1
j -- p j v
12Analyse
Cmin(N) N-1 Cmax(N) S i2..N i
Q(N2)Mmin(N) 2(N-1) Mmax(N) S i2..N i1
Q(N2) Für die Abschätzung der Werte C mit und M
mit kann man davon ausgehen, daß im Mittel die
Hälfte der maximalen Vergleiche/Bewegungen
ausgeführt werden müssen. Auch hier erhält man
also Q(N2).
13Bubblesort
Methode Jeweils 2 benachbarte Schlüssel werden
verglichen. Ist ai gt ai1 , so werden items
vertauscht. Größtes Element steigt in jedem
Durchgang ans Ende (wie Blase, engl. bubble, nach
oben). Terminierung wenn keine Vertauschung mehr
erfolgt ist, oder spätestens nach N-1
Durchläufen.
14Funktion bubblesort
void bubble (int a, int N) int i,
j,t,flag for ( i N i gt 1 i--) flag
1 for (j 2 j lt i j ) if ( a j-1
gt a j ) flag 0 t a j-1 a
j-1 a j a j t if (flag)
break / flag 0 heißt Abbruch, da keine
Vertauschung mehr erforderlich war. /
15Analyse
Cmin(N) N-1 Cmax(N) (N-1) (N-2) ... 1
N(N-1) / 2 Q(N2) Mmin(N) 0 Mmax(N) 3
Cmax(N) Q(N2) Dieselbe Abschätzung erhält man
für die mittlere Laufzeit. Bubblesort
asymmetrisch gut, wenn viele Elemente in der
richtigen Reihenfolge sind, schlecht sonst.
16Quicksort
- erfahrungsgemäß eine der schnellsten Methoden
- Divide and Conquer-Verfahren
- Zerlege die Folge F a1,...,an in zwei
Folgen F1 und F2, so daß gilt - Für jeden Schlüsselwert ki1 der Folge F1 und
jeden Schlüsselwert ki2 der Folge F2 gilt die
Beziehung ki1 lt ki2 , - d. h. jedes Element der ersten Teilfolge ist
kleiner als jedes Element der zweiten Teilfolge. - Führe diese Zerlegung wiederum für beide Folgen
F1 und F2 durch, usw. - Das Verfahren bricht für eine Teilfolge ab, wenn
diese einelementig ist. - Nach dem Abbruch des Verfahrens ist dann die
gesamte Folge sortiert. Wir beschreiben den
Vorgang des Zerlegens und Zusammensetzens etwas
genauer
17Zerlegung
(i) Wähle ein Element (Pivotelement) v aus der
Folge a1,...,an, etwa va1 (ii) Durchs
uche die Folge von links, bis ein Element ai
mit v lt ai gefunden wurde. (iii) Durchsuche
die Folge von rechts, bis ein Element aj mit
aj lt v gefunden wurde. (iv) Vertausche beide
Elemente (v) Wiederhole (ii), (iii) und (iv) so
lange, bis i gt j gilt. Anschließend wird das
Element v a1 mit aj vertauscht und es gilt
für die neue Folge a1,...,aj-1, x,
aj1,...,an ai1 lt v lt ai2, für alle i1
? 1,...,j-1, i2 ? j1,...,n Daraufhin wird
der gesamte Prozeß für die Teilfolgen
a1,...,aj-1 und aj1,..., an
durchgeführt, und es ist kein Zusammensetzen der
Ergebnisse mehr erforderlich.
18Beispiel zu Quicksort
Wir betrachten die Folge
j
i
44
55
12
42
94
6
18
67
und sortieren sie bezüglich der Ordnung lt .
Zuerst haben wir das Vergleichselement v a1
44 gewählt. Mit der Variablen i sind wir von
links so weit gelaufen, bis wir auf ein Element
gestoßen sind, das größer ist als 44. Das gleiche
geschah von rechts mit der Variablen j, bis ein
Element gefunden wurde, das kleiner ist als v,
ai und aj werden nun vertauscht und wir
erhalten
i
j
18
44
12
42
94
55
6
67
19Mit i sind wir anschließend auf das Element a5
94 und mitj auf a6 6 gestoßen. Wiederum
werden beide vertauscht
i
j
44
18
12
42
6
67
55
94
Nachdem wir mit Hilfe von i und j die Folge
weiter durchsucht haben, gilt jetzt i gt j, und
damit ist das Abbruchkriterium der Zerlegung
erreicht. Jetzt werden a1 und aj vertauscht,
und wir erhalten
42
12
18
6
67
94
44
55
Jetzt gilt Alle Elemente der linken Teilfolge
sind kleiner oder gleich v, und jedes Element der
rechten Teilfolge ist größer oder gleich v. Das
Verfahren wird nun auf beide Teilfolgen
angewendet
6
18
12
42
55
94
67
und
20C-Programm zu Quicksort
void quicksort ( int a , int l , int r )
/ ausgewähltes Element (Pivotelement) steht
links. / int v, i, j, t if ( r gt l)
v a l i l j r 1 / v
ist das Pivotelement/ for ( )
while ( a i lt v) / s. Bemerkung
unten / while ( a - -j gt v ) if (
i gt j ) break t ai ai aj aj
t t a j a j a l
a l t quicksort ( a , l , j -1 )
quicksort ( a , j 1 , r )
Bemerkung Im Ausgangsfeld muss vor Start ein
Stopper rechts vom letzten Element der Liste
abgelegt werden, der beim ersten Durchlauf die
while(ai ... Schleife terminiert. In der
Rekursion ist das nicht erforderlich, weil dann
rechts der betrachtetenTeilliste Schlüssel gt v
stehen.
21Analyse 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)
22Shellsort
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 ? kih Array a wird nun mit Einfügesort ht
sortiert, dann ht-1 sortiert usw. bis a
1-sortiert und damit sortiert ist.
23Beispiel Inkremente 4,2,1
16 3 22 11 9 7 4 4-Sortieren 3
Zuweisungen 9 3 22 11 16 7 4 3
Zuweisungen 9 3 4 11 16 7 22
2-Sortieren 3 Zuweisungen 4 3 9 11 16
7 22 3 Zuweisungen 4 3 9 7 16 11
22 1-Sortieren 3 Zuweisungen 3 4 9
7 16 11 22 3 Zuweisungen 3 4 7 9
16 11 22 3 Zuweisungen 3 4 7 9 11
16 22
24Normalverfahren
16 3 22 11 9 7 4 3 Zuweisungen 3
16 22 11 9 7 4 4 Zuweisungen 3 11
16 22 9 7 4 5 Zuweisungen 3 9
11 16 22 7 4 6 Zuweisungen 3 7 9
11 16 22 4 7 Zuweisungen 3 4 7
9 11 16 22 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.
25Heapsort
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 höchstens 2 ausgehende Kanten
besitzen (Knoten ohne ausgehende Kanten heißen
Blätter) und wenn zwischen dem linken und re.
Sohn eines Knotens unterschieden wird. 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. Definition 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).
26Beispiel
9
6
7
4
3
2
Heaps lassen sich einfach als Arrays realisieren
Knoten werden einfach von der Wurzel beginnend
auf jeder Ebene von links nach rechts
durchnumeriert. Knoten ai hat Söhne a2i und
a2i1. Heap-Bedingung ai gt a2i und ai
gt a2i1 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)
27Versickere
void downheap (a, N, k) int j, v v
ak while (k lt N/2) jkk if (jltN
aj lt aj1) j if (v gt aj)
break ak aj k j ak v
28Heapsort
heapsort (int a , int N) /sortiert a1 bis
aN / int k, t /wandle a1 bis aN in
Heap um/ for (kN/2 kgt1 k- -) downheap
(a, N, k) while (Ngt1) /vertausche a1
und aN und laß a1 versickern/ t a1
a1 aN aN 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.
29(No Transcript)
30(No Transcript)
31(No Transcript)
32(No Transcript)
33Mergesort
John von Neumann, 1945 Algorithmus Mergesort
(F) Falls F leer oder einelementig -gt
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.
34Funktion mergesort
mergesort (int a, int l, int r) /sortiert
al bis ar nach aufsteigenden
Schlüsseln/ int i, j, k, m if (rgt1)
/Folge hat mindestens 2 Elemente/
m (rl)/2 /Mitte der Folge bestimmen/
mergesort(a, l, m)
mergesort(a, m1, r) for (im1
igt1 i--) bi-1 ai-1 for (jm jltr j)
brm-j aj1 for (klkltrk)
/Zweiweg-Mischen/ ak(biltbj) ?
bi bj--
35Komplexitä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.
36Beispiel
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
37Natü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. Beisp
iel 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.
38Anmerkung wie läßt sich Grad der
Vorsortierungeiner Folge F k1,...,kn von
Schlüsseln messen?
Vorschlag 1 Zahl der Inversionen
(Vertauschungen) von F inv(F) (i,j) 1? i lt
j ? n, ki gt 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 lt n, ki1 lt 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)
39Beispiele
F 3 6 5 7 9 1 8 0 2 4 1 0 3 2 5
4 7 6 9 8 inv(F) 3544513000 25
1010101010 5 runs(F)
4 6 3 6 5 7 9 1 8 0 2 4 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
40Zusammenfassung 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
Quicksort n log n n log n n2
log n
Heapsort n log n n log n n log
n 1
Bucketsort n n n log n, n2 n
Mergesort n log n n log n n
log n n