Informatik I Sortierverfahren Sortierverfahren Sortierverfahren

Werbung
Informatik I
3. Kapitel
Sortierverfahren
Rainer Schrader
Zentrum für Angewandte Informatik Köln
28. Mai 2008
1/1
2/1
Sortierverfahren
Sortierverfahren
• ein bedeutender Teil der kommerziell genutzten Rechenzeit wird für
Sortieren verwendet
• daraus resultiert ein Bedarf nach guten Sortierverfahren
Gliederung
• gegeben:
• Folge von Datensätzen a1 , a2 , . . . , an ,
• Vorbemerkungen
• allgemeine Sortierverfahren
• untere Schranken
• die Datensätze enthalten Schlüsselfelder k1 , k2 , . . . , kn ,
• auf den Schlüsseln ist eine Ordnungsrelation „≤” erklärt
• spezielle Sortierverfahren
• gesucht:
• Permutation
π : {1, 2, . . . , n} → {1, 2, . . . , n}
• mit
kπ(1) ≤ kπ(2) ≤ . . . ≤ kπ(n) .
3/1
4/1
Sortierverfahren
Sortierverfahren
Man unterscheidet:
Gliederung
• internes Sortieren: alle Daten sind im Hauptspeicher
• externes Sortieren: Daten liegen auf Sekundärspeichern
• Vorbemerkungen
• allgemeine Sortierverfahren
• spezielle Sortierverfahren: lediglich Schlüsselvergleich erlaubt
• untere Schranken
• spezielle Sortierverfahren
• allgemeine Sortierverfahren: weitere Operationen sind erlaubt
5/1
6/1
Sortierverfahren
Sortierverfahren
Vereinfachungen
Laufzeitmessung
• die Schlüssel sind natürliche Zahlen
• wir identifizieren die Datensätze mit ihren Schlüsseln:
• Anzahl der Schlüsselvergleiche (Comparisons C)
• Anzahl der Bewegungen von Datensätzen (Movements M )
A(i ).key ∼ A(i )
• im besten Fall Cmin (n), Mmin (n)
• im schlechtesten Fall Cmax (n), Mmax (n),
• im Durchschnittsfall Cavg (n), Mavg (n),
gewünschtes Ergebnis nach dem Sortieren:
A(1) ≤ A(2) ≤ . . . ≤ A(n)
wobei der Durchschnitt wird über alle n! möglichen Anfangsanordnungen
gebildet wird.
7/1
8/1
Sortierverfahren
Sortierverfahren
Gliederung
• Vorbemerkungen
Sortieren durch Auswahl (selection sort )
• allgemeine Sortierverfahren
• selection sort (Sortieren durch Auswahl)
• insertion sort (Sortieren durch Einfügen)
• suche kleinsten Schlüssel ; Position j1 ∈ {1, 2, . . . , n}
• vertausche A(1) mit A(j1 ),
• bubble sort (Blasensortierung)
• quick sort
• heap sort
• suche kleinsten Schlüssel in {2, 3, . . . , n}, ; Position j2 ,
• vertausche A(2) mit A(j2 ),
• merge sort
• ...
• untere Schranken
• spezielle Sortierverfahren
9/1
10 / 1
Sortierverfahren
Sortierverfahren
Programmskizze
Beispiel:
• A(1) A(2) A(3) A(4) A(5)
• 5
2
4
3
1
• 5
2
4
3
1
•
1
2
4
3
5
•
1
2
4
3
5
•
1
2
4
3
5
•
1
2
4
3
5
•
1
2
3
4
5
•
1
2
3
4
5
•
1
2
3
4
5
for i = 1 to n-1 do
// Bestimme Position des Minimums unter A(i),...,A(n)
minpos = i
for j = i+1 to n do
if (A(j) < A(minpos)) minpos = j
// (*)
end do
// Vertausche
t = A(minpos)
A(minpos) = A(i)
A(i) = t
end do
11 / 1
// wäre eigentlich
// nicht nötig,
// wenn i = minpos
(**)
(**)
(**)
12 / 1
Sortierverfahren
Sortierverfahren
Analyse
• kann die „Minimum-Position” in der jeweiligen Restfolge effizienter
bestimmen werden?
• Vergleiche in (*):
Cmin (n) = Cmax (n) = Cavg (n) =
• Antwort: NEIN, wenn man nur Vergleiche zulässt, denn:
n−1
n−1
X
X
n(n − 1)
(n − i ) =
i =
= Θ(n 2 )
2
i =1
i =1
Satz
• Bewegungen in (**):
Jeder Algorithmus zur Bestimmung des Minimums von n Schlüsseln, der
allein auf Schlüsselvergleichen basiert, muss mindestens
n − 1 Schlüsselvergleiche durchführen.
Mmin (n) = Mmax (n) = Mavg (n) = 3(n − 1) = Θ(n)
13 / 1
14 / 1
Sortierverfahren
Sortierverfahren
Satz
Jeder Algorithmus zur Bestimmung des Minimums von n Schlüsseln, der
allein auf Schlüsselvergleichen basiert, muss mindestens
n − 1 Schlüsselvergleiche durchführen.
Einsatz von selection sort
falls
Beweis:
• Bewegungen von Datensätzen teuer,
• „Wettkampf” zwischen Schlüsseln,
• von zwei Schlüsseln ki und kj (i 6= j ) scheidet der größere aus,
• bei jedem Wettkampf scheidet ein Teilnehmer aus,
• Vergleiche zwischen Schlüsseln billig.
• wir benötigen n − 1 Wettkämpfe zur Ermittlung des Siegers.
15 / 1
16 / 1
Sortierverfahren
Sortierverfahren
Gliederung
• Vorbemerkungen
• allgemeine Sortierverfahren
• selection sort (Sortieren durch Auswahl)
• insertion sort (Sortieren durch Einfügen)
• bereits im letzten Kapitel behandelt, aber etwas bessere
Implementierung:
• bubble sort (Blasensortierung)
• quick sort
• heap sort
• merge sort
• untere Schranken
• spezielle Sortierverfahren
17 / 1
Sortierverfahren
1.
2.
Sortierverfahren
for i = 2 to n do
key = A(i)
for i = 2 to n do
key = A(i)
// füge A(i) in die sortierte Folge A(1...i-1) ein
j = i
A(0) = key
// Trick, um die while-Schleife
// zu vereinfachen
while (A(j-1) > key) do
// (*)
// Verschiebe
A(j) = A(j-1)
// (**)
j = j - 1
end while
A(j) = key
// (**)
end do
// füge A(i) in die sortierte Folge A(1...i-1) ein
3.
j = i - 1
4.
5.
6.
while (j > 0 und A(j) > key) do
A(j+1) = A(j)
j = j-1
end while
7.
A(j+1) = key
18 / 1
end do
19 / 1
20 / 1
Sortierverfahren
Sortierverfahren
Definition
Sei π = hk1 , k2 , . . . , kn i eine Permutation von n verschiedenen Zahlen
Analyse
• Cmin (n) = n − 1, Mmin (n) = 2(n − 1)
• Cmax (n) =
Pn
• Mmax (n) =
Pn
i =2
• ein Paar (ki , kj ) heißt Inversion von π, falls i < j und ki > kj ,
(schon sortiert)
• Inversionszahl I(π): die Gesamtanzahl der Inversionen von π
i = Θ(n 2 ),
i =2 (i
+ 1) = Θ(n 2 )
(umgekehrt sortiert)
Beispiel:
• sei π = (5, 6, 1, 2)
• Inversionen treten auf bei (5, 1), (5, 2), (6, 1) und (6, 2)
• somit ist die Inversionszahl I(π) = 4.
• Durchschnittsfall:
21 / 1
22 / 1
Sortierverfahren
Sortierverfahren
Definition
Sei π = hk1 , k2 , . . . , kn i eine Permutation von n verschiedenen Zahlen
Lemma
• ein Paar (ki , kj ) heißt Inversion von π, falls i < j und ki > kj ,
Sei π eine Permutation auf {1, 2, . . . , n} und π̂ die Reflexion von π. Dann
ist jede Inversion von hn, n − 1, . . . , 1i entweder eine Inversion von π oder
eine Inversion von π̂.
• Inversionszahl I(π): die Gesamtzahl der Inversionen von π,
• die Permutation π̂ = hkn , kn−1 , . . . , k1 i ist die Reflexion von π.
Beweis: trivial.
π = (5, 6, 1, 2) −→ π̂ = (2, 1, 6, 5).
Also gilt
I(π) + I(π̂) =
Die Inversionszahl ist ein Maß für die „Vorsortiertheit“ von π:
n(n − 1)
.
2
• 0 für eine aufsteigend sortierte Folge,
•
Pn
i =1 (n
− i) =
n(n−1)
2
= Θ(n 2 ) für eine absteigend sortierte Folge.
23 / 1
24 / 1
Sortierverfahren
Sortierverfahren
Satz
• bezeichne Sn die Menge aller Permutationen auf {1, 2, . . . , n}
• dann ist die durchschnittliche Anzahl der Inversionen gegeben durch
A(n) =
Die durchschnittliche Anzahl der Inversionen einer Permutation auf
{1, 2, . . . , n} ist n(n−1)
.
4
1 X
I(π),
n!
Beweis:
π∈Sn
2A(n) =
1 X
(I(π) + I(π̂))
n!
π∈Sn
• ebenso gilt
A(n) =
1 X
I(π̂)
n!
=
1 X n(n − 1)
n!
2
π∈Sn
π∈Sn
n(n − 1)
=
2
• damit folgt:
25 / 1
26 / 1
Sortierverfahren
Sortierverfahren
Analyse des Durschnittsfalls von insertion_sort
Analyse des Durschnittsfalls von insertion_sort
for i = 2 to n do
key = A(i)
// füge A(i) in die sortierte Folge A(1...i-1) ein
j = i
A(0) = key
// Trick, um die while-Schleife
// zu vereinfachen
while (A(j-1) > key) do
// (*)
// Verschiebe
A(j) = A(j-1)
// (**)
j = j - 1
end while
A(j) = key
// (**)
end do
• für jedes Element 2 ≤ i ≤ n wird die while-Schleife in
(*) durchlaufen
• (A(j-1) ≤ k) beendet die Schleife
• ; Anzahl der Abbrüche = n − 1
• bei (A(j-1) > k) wird der Schleifendurchlauf fortgesetzt
• (A(j-1) > k) entspricht eineindeutig einer Inversion der Eingabefolge
; Anzahl der Nichtabbrüche = Anzahl der Inversionen
27 / 1
28 / 1
Sortierverfahren
Sortierverfahren
Insgesamt gilt also:
n(n − 1)
Cavg (n) = (n − 1) +
4 }
| {z } | {z
Abbrüche
• die quadratische Laufzeit hängt zusammen mit der Anzahl der
Inversionen
Inversionen
(n + 4)(n − 1)
4
= Θ(n 2 )
• ist diese klein, etwa O(n), so läuft insertion_sort in linearer Zeit
=
29 / 1
30 / 1
Sortierverfahren
Sortierverfahren
Gliederung
• Vorbemerkungen
bubble sort (Blasensortierung)
• allgemeine Sortierverfahren
• selection sort (Sortieren durch Auswahl)
• wiederholtes Vertauschen benachbarter Datensätze (falls nötig), von
• insertion sort (Sortieren durch Einfügen)
links nach rechts,
• bubble sort (Blasensortierung)
• quick sort
• dann dasselbe von links bis zur vorletzten Position, usw.
• heap sort
• sieht aus wie „aufsteigende Luftblasen”
• merge sort
• untere Schranken
• spezielle Sortierverfahren
31 / 1
32 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
5
2
4
3
1
2
5
4
3
1
2
4
5
3
1
bubble_sort
2
4
3
5
1
2
4
3
1
5
2
4
3
1
5
2
3
4
1
5
2
3
1
4
5
for i = n down to 2
for j = 2 to i do
if (A(j-1) > A(j)) do
// (*)
vertausche A(j) und A(j-1) // (**)
end if
end do
end do
2
3
1
4
5
2
1
3
4
5
1
2
3
4
5
33 / 1
34 / 1
Sortierverfahren
Sortierverfahren
Analyse:
Gliederung
• Vergleiche in (*):
• Vorbemerkungen
n
X
n(n − 1)
Cmin (n) = Cmax (n) = Cavg (n) =
= Θ(n 2 )
(i − 1) =
2
• allgemeine Sortierverfahren
• selection sort (Sortieren durch Auswahl)
i =2
• insertion sort (Sortieren durch Einfügen)
• Bewegungen in (**):
• bubble sort (Blasensortierung)
• quick sort
Mmin (n) = 0
n(n − 1)
= Θ(n 2 )
2
Mavg (n) = Θ(n 2 )
Mmax (n) = 3
(absteigend sortiert)
• heap sort
(ohne Beweis)
• merge sort
• untere Schranken
• spezielle Sortierverfahren
• bubble_sort ist populär, aber schlecht.
35 / 1
36 / 1
Sortierverfahren
Sortierverfahren
Vorgehen von quick sort
• falls F die leere Folge ist oder nur ein Element hat, so bleibt
F unverändert, sonst
• wir könnten quicksort rekursiv mit lokalen, zu sortierenden Feldern
• divide:
implementieren
• wähle „Pivotelement“ k von F ,
• es folgt eine Implementierung, die in situ sortiert
• teile F ohne k in Teilfolgen F1 und F2 mit
• dazu tauschen wir die kleinen Schlüssel nach vorn und die großen nach
• F1 enthält nur Elemente ≤ k
hinten
• F2 enthält nur Elemente ≥ k
• die Rekursion sortiert dann immer Teilintervalle von [1, . . . , n]
• conquer:
• wir wählen als Pivotelement stets das „rechte“ Element
• quicksort(F1); quicksort(F2);
• danach sind F1 und F2 sortiert
• combine:
• bilde F durch Aneinanderfügen in der Reihenfolge F1 , k , F2 .
37 / 1
38 / 1
Sortierverfahren
Sortierverfahren
Vorgehen zur Umsortierung
Sei v = A(r ) der Pivotschlüssel:
wir füllen A(0) mit einem hinreichend kleinen Element, um Schleifenabfragen
zu vereinfachen:
• ein Zeiger i wandert vom linken Intervallende nach rechts
• er stoppt, sobald er ein Element mit A(i ) ≥ v findet
• ein Zeiger j wandert vom rechten Intervallende nach links
• er stoppt, sobald er ein Element mit A(j ) ≤ v findet
begin
A(0) = kleine_Zahl
quicksort(A,1,n)
end
l=4
wobei kleine_Zahl ≤ minni=1 A(i)
Position
r=9
3
4
5
6
7
8
9
10
...
8
6
2
3
7
4
...
Pivotelement
Schlüssel
i
j
i
39 / 1
j
Anfangsposition
1. Halt
40 / 1
Sortierverfahren
Sortierverfahren
Vorgehen zur Umsortierung
Vorgehen zur Umsortierung
Sei v = A(r ) der Pivotschlüssel:
• ein Zeiger i wandert vom linken Intervallende nach rechts
• er stoppt, sobald er ein Element mit A(i ) ≥ v findet
• ein Zeiger j wandert vom rechten Intervallende nach links
Sei v = A(r ) der Pivotschlüssel:
• ein Zeiger i wandert vom linken Intervallende nach rechts
• er stoppt, sobald er ein Element mit A(i ) ≥ v findet
• ein Zeiger j wandert vom rechten Intervallende nach links
• er stoppt, sobald er ein Element mit A(j ) ≤ v findet
• die Elemente A(i ) und A(j ) werden vertauscht
l=4
• er stoppt, sobald er ein Element mit A(j ) ≤ v findet
• die Elemente A(i ) und A(j ) werden vertauscht
r=9
• danach gilt:
Position
3
4
5
6
7
8
9
10
Pivotelement
Schlüssel
...
8
6
2
3
7
i
j
j
i
...
4
3
6
2
8
i
7
4
• A(k ) ≤ v für alle k ≤ i und
...
• A(k ) ≥ v für alle k ≥ j
Anfangsposition
1. Halt
• die Zeiger wandern weiter bis i ≥ j gilt.
...
j
41 / 1
42 / 1
Sortierverfahren
Sortierverfahren
• wir haben somit stets A(j ) ≤ v ≤ A(i ) und i ≤ j + 1
Sei i ≥ j :
• wenn beide nicht halten, gilt für i = j : v < A(j ) = A(i ) < v
• i hält: dann ist A(i ) ≥ v , A(i − 1) < v
• per Konstruktion gilt:
• A(k ) ≤ v für k < i
• A(k ) ≥ v für k > j
h
i
h
i
• somit: A(l ), . . . , A(j ) ≤ v ≤ A(i ), . . . , A(r )
• j hält an der Stelle i − 1
• und es gilt A(j ) ≤ v ≤ A(i )
• wir können die Elemente A(i ) und A(r ) vertauschen
• j hält: dann ist A(j ) ≤ v , A(j + 1) > v
• und die Rekursion aufrufen für die Intervalle
• i hält an der Stelle j + 1
i
A(l ), . . . , A(i − 1) und
h
i
• A(i + 1), . . . , A(r )
• und es gilt A(j ) ≤ v ≤ A(i )
•
43 / 1
h
44 / 1
Sortierverfahren
Sortierverfahren
Ablauf quicksort(A,4,9)
quicksort(A,l,r)
l=4
if (r > l) then do
i = l-1
j = r
v = A(r)
repeat
do i = i+1 while (A(i) < v)
do j = j-1 while (A(j) > v)
if (i >= j) goto PIVOT
vertausche A(i) und A(j)
end repeat
PIVOT: vertausche A(i) und A(r)
quicksort(A,l,i-1)
quicksort(A,i+1,r)
end if
Position
r=9
3
4
5
6
7
8
9
10
...
8
6
2
3
7
4
...
Pivotelement
Schlüssel
// Pivotelement
i
j
j
i
//
(*)
//
(*)
// i Pivotposition
//
(**)
//
...
...
(**)
...
3
3
3
6
2
i
j
2
6
j
i
2
4
8
7
4
Anfangsposition
1. Halt
...
2. Halt
8
7
4
...
3. Halt
8
7
6
...
45 / 1
46 / 1
Sortierverfahren
Sortierverfahren
k1 < k2 < · · · < kn
quicksort(A,1,n)
Terminierung der while-Schleifen:
?
• erste Schleife klar durch Wahl des Pivotelements „ganz rechts“.
?
kn
k1 < k2 < · · · < kn−1
quicksort(A,1,n-1)
• zweite Schleife:
?
• quicksort(A,1,n) durch Wahl von A(0)
• alle rekursiven Aufrufe der Form quicksort(A,l,r):
?
kn−1
k1 < k2 < · · · < kn−2
quicksort(A,1,n-2)
• in Position l − 1 steht:
• A(0), falls l = 1
?
• ein Pivotelement einer vorangehenden Aufteilung, sonst.
?
kn−2
.
.
.
?
Das Programm ist auch korrekt, falls Schlüssel mehrfach vorkommen.
k1 < k2
quicksort(A,1,2)
Allerdings gibt es dann unnötige Vertauschungen.
?
k1
47 / 1
?
k2
48 / 1
Sortierverfahren
Sortierverfahren
worst-case Schlüsselvergleiche:
average-case Schlüsselvergleiche:
• aufsteigend sortierte Folge !!!
•
n
X
Cmax (n) =
i =1
• wir wollen zeigen , dass quicksort im Mittel nur O(n log n)
n(n + 1)
i =
= Θ(n 2 )
2
Vergleiche benötigt
• dazu benötigen wir einen Hilfssatz über eine Rekursion
Lemma
best-case Schlüsselvergleiche:
• die durch die Aufteilung erhaltenen Folgen F1 und F2 haben immer
Die Rekursionsgleichung der Form

a1
T (n) =
an + bn T (n − 1)
ungefähr die gleiche Länge
• dann halbieren sich die zu sortierenden Intervalle in jedem Schritt
• ; die Höhe des Rekursionsbaums ist Θ(log n)
• zur Aufteilung aller Intervalle auf jedem Niveau werden
hat die Lösung T (n) =
n `
P
für n = 1
für n ≥ 2
´
Πnj=i +1 bj ai .
i =1
Θ(n) Vergleiche durchgeführt, also
Dabei ist wie üblich das Produkt über eine leere Indexmenge 1.
Cmin (n) = Θ(n log n)
49 / 1
50 / 1
Sortierverfahren

T (n) =
a1
an + bn T (n − 1)
ff
für n = 1
für n ≥ 2
; T (n) =
n
X
`
Sortierverfahren
average-case Schlüsselvergleiche:
´
Πnj=i +1 bj ai .
• übliche Grundannahme:
i =1
• alle Schlüssel sind verschieden (oBdA. in {1, 2, . . . , n}),
Beweis: (Induktion über n)
• alle Permutationen sind gleich wahrscheinlich
√
T (1) = a1
• daraus ergibt sich:
T (n) = an + bn T (n − 1)
0
1
n−1
n−1
X
Y
@
= an + bn
bj A ai
i =1
= an +
n−1
X
0
=
0
n
Y
@
i =1
j =i +1
n
Y
@
i =1
n
X
• jede Zahl k ∈ {1, 2, . . . , n} tritt mit gleicher Wahrscheinlichkeit
1
als Pivotelement an Position n auf
n
• das Pivotelement k erzeugt zwei Folgen der Längen
(k − 1) und (n − k )
• beide sind zufällig:
1
bj A ai
j =i +1
1
• werden sämtliche Folgen mit n Elementen mit dem Pivotelement
k geteilt,
bj A ai
• so erhält man sämtliche Folgen der Längen (k − 1) und (n − k ).
j =i +1
51 / 1
52 / 1
Sortierverfahren
Sortierverfahren

T (n) =
Satz
Die mittlere Anzahl von Vergleichen und die mittlere Laufzeit von Quicksort
beträgt O(n log n).
c
2
n
Pn−1
k =1 T (k ) + d (n − 1)
Daraus folgt:
Beweis:
(n + 1)T (n + 1) = dn(n + 1) + 2
Sei T (n) die Laufzeitfunktion, d.h. für Konstanten c und d
8
>
< 0
c
T (n) =
“
”
>
: 1 Pn
k =1 T (k − 1) + T (n − k ) + d (n − 1)
n
gilt:
nT (n) = dn(n − 1) + 2
für n = 0
für n = 1
T (n) =
2
n
Pn−1
k =1
T (k ) + d (n − 1)
T (k ) und
n−1
X
T (k )
k =1
für n ≥ 2
Subtraktion dieser beiden Gleichungen ergibt:
T (n + 1) =
Einsetzen T (0) = 0:
c
n
X
k =1
wobei d (n − 1) der Aufteilungsaufwand für eine Folge der Länge n ist.

für n = 1
für n ≥ 2
2n
n+2
d+
T (n).
n+1
n+1
Somit:
für n = 1
für n ≥ 2
T (1) = c =: a1
und
T (n) = an + bn T (n − 1) mit ai :=
2(i − 1)
i +1
d und bi :=
,i ≥ 2
i
i
53 / 1
54 / 1
Sortierverfahren
T (1) = c
Sortierverfahren
und
Zusammenfassung quick sort :
2(i − 1)
i +1
d und bi =
i
i
T (n) = an + bn T (n − 1) mit ai =
Schlüsselvergleiche:
• Cmin (n) = Θ(n log n)
• Cmax (n) = Θ(n 2 )
Mit dem vorigen Lemma folgt dann:
T (n) =
n
X
`
• Cavg (n) = Θ(n log n)
´
Πnj=i +1 bj ai
i =1
Bewegungen:
n
=c
n + 1 X n + 1 2(i − 1)
+
d
2
i +1
i
• Mmin (n) = Θ(n) (aufsteigend sortierte Folge)
• Mmin (n) = 0, falls man überflüssige Bewegungen vermeidet
i =2
n
≤c
X1
n+1
+ 2(n + 1)d
2
i
• Mmax (n) ?
i =2
= O(n log n).
(da
n
X
1
= ln n + O(1))
i
i =1
55 / 1
56 / 1
Sortierverfahren
Sortierverfahren
Mmax (n) :
Mmax (n) :
• Verfolgung eines Elements über den gesamten Sortierprozess:
Wir betrachten die Vertauschungen in einem Aufteilungsschritt:
• werden in (∗∗) zwei Elemente vertauscht
• wird dieses Element mit Bewegungskosten belastet,
• dann reduziert sich die Länge der Teilfolge, in der es sich befindet,
auf höchstens die Hälfte
• das kann höchstens log n mal passieren,
• dann ist das eine kleiner, das andere größer als das Pivotelement
• also ist die Anzahl der Vertauschungen bei einem Aufteilungsschritt
höchstens so groß wie die Anzahl der Elemente in der kürzeren Teilfolge
• danach hat die Teilfolge nur noch ein Element
• wir belasten die Kosten für eine Vertauschung dem Element, das in der
• das gilt für jedes der n Elemente, also
kürzeren Teilfolge landet
• Mmax (n) = O(n log n)
• d.h. jedes Element wird in einem Aufteilungsschritt mit höchstens
konstanten Kosten belastet.
• Mavg (n) scheint offen
57 / 1
58 / 1
Sortierverfahren
Sortierverfahren
Diskurs: Rekursive Funktionen und Stapel
Abschließende Bemerkungen zu quicksort
• bei jedem rekursiven Aufruf werden die aktuellen Werte der Parameter
• das beste Verfahren in der Praxis
und der lokalen Variablen in einem Stack „gepushed“, und nach
Beendigung des rekursiven Aufrufs wieder „gepopped“
• es gibt viele Varianten, auch solche, die den worst-case Fall einer
sortierten Folge verhindern, z.B.:
• wir haben gesehen, dass der Stapel für quicksort im worst case
• zufällige Wahl des Pivotelements,
Θ(n) Platz benötigt
• mittleres (Median) von drei zufällig gewählten Elementen.
• dies kann auf Θ(log n) gedrückt werden, wenn man stets das kleinere
Intervall sortiert
• man kann quicksort mit Hilfe von Stapeln ohne rekursive Aufrufe
implementieren (Übungsaufgabe).
• warum ? (Übungsaufgabe)
59 / 1
60 / 1
Sortierverfahren
Sortierverfahren
Gliederung
• Vorbemerkungen
• allgemeine Sortierverfahren
• alle bisherigen Verfahren (außer merge sort) benötigen im worst
• selection sort (Sortieren durch Auswahl)
• insertion sort (Sortieren durch Einfügen)
case Θ(n 2 ) Zeit
• wir behandeln nun Sortierverfahren mit besserem worst-case-Verhalten
• bubble sort (Blasensortierung)
• quick sort
• im Folgenden sortieren wir aufsteigend
• heap sort
• merge sort
• untere Schranken
• spezielle Sortierverfahren
61 / 1
Sortierverfahren
62 / 1
Sortierverfahren
(Max)-Heap
• wir speichern die Schlüsselelemente F = hk1 , k2 , . . . , kn i in einem
• zur Erinnerung: in der sequentiellen Numerierung eines vollständigen
vollständigen binären Baum ab
Baums hat der Knoten i den Vater b 2i c
• der Baum heißt Heap (Haufen) oder heap-geordnet, falls gilt:
• die Schlüsselelemente sind somit heap-geordnet, wenn wir so
umnumerieren, dass für alle i ∈ {2, 3, . . . , n} gilt: ki ≤ kb i c .
• jeder Schlüssel ist mindestens so groß ist wie die Schlüssel seiner
Kinder
2
⇐⇒ auf jedem Pfad von der Wurzel zu einem Blatt fallen die
Schlüssel monoton
63 / 1
64 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
F =
1
8,
h
2
6,
3
7,
4
3,
5
4,
6
5,
7
2,
8
1
i
Methode zum absteigenden Sortierverfahren
• mache aus der Eingabefolge einen Heap,
1
• solange der Heap nicht leer ist:
8
2
3
6
5
4
6
• mache aus den restlichen Schlüsseln einen Heap.
7
5
4
3
• gib k1 aus, (Wert in der Wurzel)
• entferne k1 aus dem Heap,
7
2
8
1
66 / 1
65 / 1
Sortierverfahren
Sortierverfahren
Im Beispiel:
Im Beispiel:
Ausgabe und Entfernen von (8):
Schlüssel mit höchstem Index an die Wurzel:
1
2
3
6
7
Es bleiben
zwei
"Teilheaps"
4
5
6
7
3
4
5
2
8
1
67 / 1
1
einziger Fehler
im Heap
1
2
3
6
7
4
5
6
7
3
4
5
2
68 / 1
Sortierverfahren
Sortierverfahren
Im Beispiel:
„Versickern“ von 1 nach unten durch Vertauschen mit dem jeweils
größeren Kind:
1
1
7
7
Methode zum aufsteigenden Sortierverfahren
2
3
2
3
6
1
6
5
• statt der Ausgabe des jeweiligen Maximums an der Wurzel:
• speichere es an der Stelle des Schlüssel, der neu an die Wurzel kommt.
4
5
6
7
4
5
6
7
3
4
5
2
3
4
1
2
Ausgabe und Entfernen von (7), usw.
70 / 1
69 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
1
2
3
4
5
6
7
versickere(A, i, m)
// Versickere A(i) bis höchstens nach A(m)
8
8
6
7
3
4
5
2
1
1
6
7
3
4
5
2
8
7
6
5
3
4
1
2
2
6
5
3
4
1
7
6
4
5
3
2
1
1
4
5
3
2
6
5
4
5
3
2
2
4
1
3
5
4
3
1
2
2
3
1
4
3
2
1
1
2
3
2
1
1
2
while (2*i<=m) do
//
j = 2*i
//
if (j < m) then do
//
if (A(j) < A(j+1)) do
j = j + 1
end do
//
end if
if (A(i) < A(j)) then do //
vertausche A(i) und A(j)//
i = j
//
end do
else i = m
//
end if
end while
end
Man beachte die Analogie zu selection sort
71 / 1
i hat linkes Kind
j ist linkes Kind von i
i hat rechtes Kind j+1
nun ist j größtes Kind
(C1)
(C2)
(M2)
versickere weiter
Heap-Bedingung erfüllt
72 / 1
Sortierverfahren
Sortierverfahren
Analyse von heap sort
• nach der Konstruktion des ersten Heaps:
Konstruktion eines Heaps
• Θ(n) Bewegungen in M1 (entferne Maximum)
1. Versuch
• ein Heap mit n Elementen hat eine Höhe von dlog(n + 1)e − 1
für i = 1, . . . , n:
• somit benötigt das Versickern eines Knotens höchstens
• es sei bereits ein Heap der Größe i − 1 aufgebaut
O(dlog(n + 1)e) Schritte
• füge dem Heap ein neues Blatt hinzu
• versickere wird n − 1 mal aufgerufen
• speichere das Element i im neuen Blatt
• also im worst case Θ(n log n) Ausführungen von C1, C2, M2, d.h.
• repariere durch „aufwärtspumpen” (analog zum versickern)
Cmax (n) = Θ(n log n)
benötigt im schlechtesten Fall
und
O(n log n) Schritte.
Mmax (n) = Θ(n log n).
74 / 1
73 / 1
Sortierverfahren
Sortierverfahren
Konstruktion eines Heaps
2. Versuch: Idee
Konstruktion eines Heaps
• die Teilbäume unter den Blättern sind bereits heap-geordnet
• ≈
n
2
2. Versuch
Elemente
• lege die Elemente beliebig in einem vollständigen Baum ab
• die Teilbäume unter den Vätern von Blättern können in 3 Schritten
• in der Reihenfolge:
heapgeordnet werden
• ≈
n
4
• von „unten nach oben” und
Elemente
• von „rechts nach links”
• die Teilbäume unter den Gr0ßvätern von Blättern können in 6 Schritten
• versickere jeweils Schlüssel, deren beide „Unterbäume” bereits die
heapgeordnet werden
• ≈
n
8
Heap-Eigenschaft haben.
Elemente
.
• ..
75 / 1
76 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
1
Analyse für den Aufbau des ersten Heaps
8
• sei h die Höhe des Heaps
2
3
6
• auf Tiefe k sind höchstens 2k Schlüssel
7
• auf Tiefe k ist die Anzahl der Vergleiche und Bewegungen zum
4
6
5
3
4
2
5
Versickern jeweils proportional zu h − k
7
• die Gesamtzahl der Vergleiche und Bewegungen ist damit proportional
zu höchstens
h
X
8
1
2k (h − k ).
k =0
77 / 1
78 / 1
Sortierverfahren
Sortierverfahren
es gilt:
h
X
heapsort(A, n)
2k (h − k ) = 20 · h + 21 (h − 1) + 22 (h − 2) + . . . + 2h−1 · 1
k =0
=
h
X
// Baue einen Heap aus A[1..n]
for i=n/2 down to 1 do
versickere (A,i,n)
end do
h−k
k ·2
k =1
= 2h
h
X
k
2k
// sortiere den Heap A[1..n]
for i = n down to 2 do
vertausche A(i) und A(1)
versickere (A,1,i-1)
end do
end
k =1
≤ 2h · 2
es gilt
∞
X
k =1
≤ 2(n + 1)
!
k
=2
2k
(da h = dlog(n + 1)e − 1)
= O(n).
79 / 1
// (M1)
// versickere A(1)
80 / 1
Sortierverfahren
Sortierverfahren
Exkurs
Analyse für Heapsort
• Cmax (n) = Θ(n log n)
Prioritätsschlange (priority queues)
• Mmax (n) = Θ(n log n)
abstrakte Datenstruktur bestehend aus:
• Objekt: eine Menge S von Datensätzen mit vergleichbaren Schlüssel
• empirisch: gleiche Ordnungen im average-case
• Operationen:
quick sort ist im Durchschnitt schneller, aber der zusätzlichen
Speicherplatzbedarf beträgt
• Insert(S,x) fügt x zu S hinzu
• Maximum(S) liefert ein Element in S mit größtem Schlüssel
• bei heap sort: O(1),
• bei quick sort: O(log n).
• ExtractMax(S): wie Maximum(S) plus Entfernen des
gelieferten Elementes aus S.
81 / 1
82 / 1
Sortierverfahren
Sortierverfahren
Anwendung: „Job Scheduling“:
Gliederung
• auf einer Maschine sollen verschiedene Aufträge (Jobs) hintereinander
• Vorbemerkungen
ausgeführt werden
• allgemeine Sortierverfahren
• wenn ein Auftrag beendet ist, so folgt der mit der höchsten Priorität
• jederzeit können neue Aufträge hinzu kommen
• selection sort (Sortieren durch Auswahl)
• insertion sort (Sortieren durch Einfügen)
• bubble sort (Blasensortierung)
• quick sort
Übungsaufgabe:
• Zeigen Sie, dass man Prioritätschlangen mit Hilfe von Heaps
• heap sort
implementieren kann.
• Wieviel Zeit benötigen die drei Operationen?
• Lassen sich Prioritätsänderungen von Elementen aus S als
• merge sort
• untere Schranken
• spezielle Sortierverfahren
zusätzliche Operationen problemlos hinzufügen?
• Wenn ja, wie und wieviel Zeit benötigen sie?
83 / 1
84 / 1
Sortierverfahren
Sortierverfahren
Analyse für von merge_sort
merge_sort . . . (bereits in Kapitel 1 behandelt)
• es gilt
merge_sort(A,p,r)
if (p < r) then do
Cmin (n) =
Cmax (n) =
Cavg (n) =
Θ(n log n)
Mmin (n) =
Mmax (n) =
Mavg (n) =
Θ(n log n).
• Mergesort benötigt Θ(n) zusätzlichen Speicherplatz (Listenzeiger)
q = (p+r)/2
merge_sort(A,p,q)
merge_sort(A,q+1,r)
merge(A,p,q,r)
• als Datenstruktur eignen sich auch verkettete Listen, da alle Teilfolgen
nur sequentiell verarbeitet werden
• es werden keine Daten bewegt, nur Zeiger verändert (vorteilhaft, wenn
die dat-Komponenten groß sind)
end if
end
• Mergesort ist daher auch als externes Sortierverfahren geeignet (wenn
z.B. die Daten auf Bändern liegen):
85 / 1
86 / 1
Sortierverfahren
Sortierverfahren
• man kann Varianten angeben, für die Cmin (n) und Mmin (n) kleiner sind
• in der Standardvariante wird die Eingangsfolge auf einelementige
externes Sortieren
Folgen herunter gebrochen
• n Datensätze liegen auf Bändern
• diese werden rekursiv mittels merge zusammengemischt
• sei k die Hauptspeichergröße mit k n
• anstelle von einelementigen Folgen können monotone Teilfolgen
• teile die Daten in d kn e Blöcke der Größe k auf
gewählt werden
• sortiere die Blöcke intern
Beispiel:
• mische die Blöcke wie in merge_sort
F =
h
1,
2,
5,
7,
|
3,
4,
6,
8
i
kann mit einem Mischvorgang sortiert werden.
87 / 1
88 / 1
Sortierverfahren
Sortierverfahren
Bemerkung zur Vorsortierung
Gliederung
• bisweilen sind Datensätze bereits vorsortiert
• Vorbemerkungen
• allgemeine Sortierverfahren
• wenige der vorgestellten Sortierverfahren nutzen Vorsortiertheit aus
(insertion sort)
• untere Schranken
• spezielle Sortierverfahren
• quicksort hat sogar maximale Laufzeit auf einer vorsortierten Folge
• wir werden in einem späteren Kapitel auf das Sortieren vorsortierter
Daten zuückkommen.
89 / 1
90 / 1
Sortierverfahren
Sortierverfahren
• Annahme: alle Schlüssel sind verschieden, oBdA. 1, 2, . . . , n.
• wir betrachten ein beliebiges allgemeines Sortierverfahren
• d.h. wir erlauben auf den Schlüsseln nur Vergleiche der Form
gilt ai ≤ aj ?
• alle bisherigen Verfahren benötigen im worst-case O(n log n)
• kann man bessere Verfahren finden?
• ; Aufteilung in Anordnungen, die ai ≤ aj erfüllen, und solche, die es
nicht erfüllen
• genauer: wieviele Vergleichsoperationen muss ein allgemeines
Sortierverfahren im worst-case durchführen?
ai : aj
≤
>
• je nach Ausgang des Vergleichs verzweigt das Verfahren
• auch die Auswahl der nächsten zu vergleichenden Schlüssel kann vom
Ausgang abhängen
91 / 1
92 / 1
Sortierverfahren
Sortierverfahren
Beispiel: insertion sort für hS1 , S2 , S3 i.
• wir halten die ausgeführten Vergleiche in einem binären Baum fest
(Entscheidungsbaum)
S1 : S
• jeder innere Knoten
2
_
>
<
S :S
2
S :S
1
3
_
>
<
S :S
1
<
• enthält ein Paar (Si , Sj ) von Schlüsseln
• repräsentiert einen Vergleich zwischen den beiden Schlüsseln
3
• hat genau zwei Söhne
• der linke Sohn repräsentiert die Situation Si < Sj
_
>
<
S :S
2
3
_
>
3
• der rechte die Situation Si ≥ Sj
_
>
<
• die Blätter entsprechen Permutationen
S S S
S S S
1
2
1
3
3
2
S3 S 1S
2
S S S
2
1
3
S2 S 3S
1
S3 S 2S
1
• jedes Blatt ist mit einer Permutation der Schlüssel S1 , . . . , Sn markiert
• die Permutation in einem Blatt erfüllt alle Bedingungen, die auf dem
Weg von der Wurzel zu diesem Blatt auftreten.
93 / 1
94 / 1
Sortierverfahren
Sortierverfahren
Definition
• maximale Anzahl von Vergleichen = maximale Tiefe eines Blattes im
• Ein Entscheidungsbaum T löst das Sortierproblem der Größe n,
Entscheidungsbaum
wenn gilt:
• es gibt eine Beschriftung der Blätter mit Permutationen Π von
{1, . . . , n}
• mittlere Anzahl von Vergleichen = mittlere Tiefe eines Blattes im
• für jede Eingabe S1 , . . . , Sn ist das erreichte Blatt genau dann mit
Π beschriftet, wenn SΠ(1) ≤ · · · ≤ SΠ(n) .
• wir wissen:
Entscheidungsbaum
Satz
Die maximale und die mittlere Tiefe eines Blattes in einem Binärbaum mit
k Blättern beträgt mindestens log k .
• ein Entscheidungsbaum kann überflüssige Vergleiche durchführen,
• er muss nur mindestens n! Blätter haben,
• und jede Permutation muss als Blatt auftreten.
95 / 1
96 / 1
Sortierverfahren
Sortierverfahren
Satz
Folgerung
Jeder Entscheidungsbaum-Algorithmus benötigt im worst-case und im Mittel
log n! = Ω(n log n) Vergleiche, um n Elemente zu sortieren.
Heapsort und Mergesort sind asymptotisch zeitoptimale Sortieralgorithmen.
Beweis:
• der Entscheidungsbaum hat mindestens n! Blätter
• nach obigem Satz ist die maximale und mittlere Anzahl der Vergleiche
• die untere Schranke von Ω(n log n) bleibt erhalten, auch wenn die
Operationen +, −, ·, / auf den Schlüsseln erlaubt sind,
log n!
• wir werden gleich zeigen, dass wir eine mittlere Laufzeit von
n
• es gilt: n! ≥ n 2
• somit: die maximale und mittlere Anzahl der Vergleiche ist von der
O(n) erreichen können, wenn wir die Operation d e zulassen.
Ordnung Ω(n log n).
97 / 1
98 / 1
Sortierverfahren
Sortierverfahren
Gliederung
• wir haben bisher zum Sortieren lediglich den Vergleich von Schlüsseln
• Vorbemerkungen
• allgemeine Sortierverfahren
• untere Schranken
zugelassen,
• wir wollen jetzt erlauben, dass die spezielle Natur der Schlüssel
ausgenutzt werden kann
• spezielle Sortierverfahren
99 / 1
100 / 1
Sortierverfahren
Sortierverfahren
radix sort: Sortieren durch Fachverteilung
Gliederung
• allgemeine Sortierverfahren
• untere Schranken
• Annahme: Die Schlüssel sind m-adische Zahlen der Länge l .
• Beispiele:
• spezielle Sortierverfahren
• m = 10: Dezimalzahlen
• m = 2: Dualzahlen
• radix sort (Sortieren durch Fachverteilung)
• bucket sort
• m = 26: Wörter über dem Alphabet {a, b, . . . , z }
• Hybridsort
• allgemein: m Zahlzeichen, Basis m (Wurzel, radix)
102 / 1
101 / 1
Sortierverfahren
Sortierverfahren
Beispiele:
3 · 102 + 0 · 101 + 7 · 100
30710 =
Sortieren durch Fachverteilung
1001100112 =
8
5
4
1
0
1·2 +1·2 +1·2 +1·2 +1·2
=
25610 + 3210 + 1610 + 210 + 110
=
30710
Methode: Funktionsweise einer Lochkartensortiermaschine
1 2 3 4 5 6
80
3 0 7
4638 =
4 · 82 + 6 · 81 + 3 · 80
=
25610 + 4810 + 310
2
3
=
30710
4
0
1
5
6
=
13316 =
7
2
1
0
8
9
1 · 16 + 3 · 16 + 3 · 16
=
25610 + 4810 + 310
=
30710
103 / 1
104 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
18
radix sort
16
38
• für jede Ziffer in {0, . . . , m − 1} existiert ein Fach
77
04
76
• am Anfang ist der Stapel von Karten unsortiert
28
15
54
• Verteilen nach Position 0 von unten nach oben:
22
13
• Karte landet in Fach Fi , falls in Position 0 Ziffer i steht
40
• Sammeln: Stapel aus Fach Fm−1 auf Fm−2 auf . . . F0
• danach Positionen 1, 2, . . . , l − 1
F9
F8
F9
18
38
28
F8
77
76
F7
77
F7
F6
16
76
F6
F5
15
F5
54
F4
40
F4
04
54
F3
13
F3
38
F2
22
F2
28
22
F1
F0
F1
40
F0
18
16
15
13
04
105 / 1
106 / 1
Sortierverfahren
Sortierverfahren
Implementierung
Korrektheit von radix sort
• nach dem ersten Aufsammeln ist der Stapel nach der Position 0 sortiert
• für jedes Fach n Speicherplätze: verschwendet Platz
• nach dem zweiten Aufsammeln ist der Stapel nach den Positionen
• statt dessen:
0 und 1 sortiert
• ...
(1) vor jeder Verteilungsphase zählen, wie groß die Fächer werden,
oder
• nach dem (l − 1)-ten Aufsammeln ist der Stapel nach den Positionen
(2) Queues verwenden
0 bis l − 1 sortiert.
• wir implementieren Methode (1)
107 / 1
108 / 1
Sortierverfahren
Sortierverfahren
radixsort(A, n)
for t = 0 to l-1 do
setze c() auf 0
for i = 1 to n do
j = ziffer_m(t,A(i))
c(j) = c(j) + 1
end do
Wir verwenden eine Routine Zifferm (pos, key ):
• der Schlüssel key sei m-adisch dargestellt
• berechnet die Ziffer an Position pos:
// Feld c(0...m-1) für Fachgröße
// c(j) =
b Größe von Fach j
c(m-1) = n - c(m-1) + 1
for i = 2 to m do
c(m-i) = c(m-i+1) - c(m-i)
end do
// c(i) =
b Anfang von Fach i
(1) integer Ziffer
(2) Ziffer = Ziffer / m pos
(3) Ziffer = Ziffer mod m
for i = 1 to n do
j = ziffer_m(t,A(i))
B(c(j)) = A(i)
c(j) = c(j) + 1
end do
kopiere B() nach A()
end do
// Verteilen:
// Sammeln
109 / 1
110 / 1
Sortierverfahren
Sortierverfahren
Analyse
Nachteil:
• Laufzeit T (n) = Θ(l (m + n))
• Speicherbedarf S(n) = Θ(m + n)
• viel Speicherplatz
• bei verschiedenen Schlüsseln muss l ≥ dlogm ne sein
• für festes l und festes m ist beides linear
• ist l = c · dlogm ne für eine Konstante c, so haben wir wieder ein
Natürliche Anwendung:
Θ(n log n) Verfahren, das normalerweise schlechter als etwa Quicksort
ist
• Schlüssel mit mehreren Feldern,
• z.B. erfordert Tag/Monat/Jahr drei Phasen von Radixsort
111 / 1
112 / 1
Sortierverfahren
Lexikographische Ordnung
• sei A = {a0 , . . . , am−1 } ein Alphabet von m Buchstaben
• ein Wort ai1 . . . air ist eine Folge aus Buchstaben aij
• sei ≺ eine lineare Ordnung auf A, etwa a0 ≺ a2 ≺ . . . ≺m−1
• wir setzen die Ordnung auf Wörter fort
x ≺ y:
• entweder ist x Anfangswort von y oder
• der erste Buchstabe, in dem sich x und y unterscheiden, ist in
x kleiner als in y .
• seien x = x1 . . . xk und y = y1 . . . yl zwei Wörter über A
• Anton ≺ Antonia (i = k = 5)
• Anton ≺ Auto (i = 1 < k , i < l , aber xi +1 = n ≺ yi +1 = u)
Lexikographische Ordnung
x ist lexikographisch kleiner als y (x ≺ y), falls es ein i mit
0 ≤ i ≤ k gibt, so dass
radix sort lässt sich leicht auf die lexikographische Sortierung anpassen
• xj = yj für alle j ∈ {1, . . . , i } und
• entweder i = k < l oder
• i < k , i < l und xi +1 ≺ yi +1 .
Wir besprechen jetzt ein strukturell noch einfaches Verfahren:
113 / 1
114 / 1
Sortierverfahren
Sortierverfahren
Bucket sort
Gliederung
• es seien n natürliche Schlüssel k1 , . . . , kn zu sortieren
• allgemeine Sortierverfahren
• untere Schranken
• sei kmax der Maximalwert der Schlüssel
• erzeuge kmax Eimer (buckets)
• spezielle Sortierverfahren
• radix sort (Sortieren durch Fachverteilung)
• gehe die Schlüssel der Reihe nach durch
• bucket sort
• wirf Schlüssel ki in den Eimer mit Index ki
• Hybridsort
• sammel die Inhalte der Eimer wieder auf
115 / 1
116 / 1
Sortierverfahren
Sortierverfahren
• Eimer könne als verkettete Listen implementiert werden
Gliederung
• das Verfahren ist effizient, wenn Schlüssel mehrfach vorkommen und
• allgemeine Sortierverfahren
• untere Schranken
kmax klein ist
• auch wenn nur zwei verschiedene Schlüsselwerte 0 und
• spezielle Sortierverfahren
kmax auftreten, benötigt bucket sort kmax Eimer
• radix sort (Sortieren durch Fachverteilung)
• bucket sort
• Ausweg:
• größere Eimer, die ein Intervall abdecken
• Hybridsort
• rekursive Sortierung innerhalb jeden Eimers
118 / 1
117 / 1
Sortierverfahren
Sortierverfahren
Hybridsort
• wähle eine Konstante α > 0 und erzeuge k = dαne leere Körbe,
• wirf xi in den Korb dkxi e
• Annahme: Die Schlüssel sind n reelle Zahlen x1 , . . . , xn (o.B.d.A.
xi ∈ (0, 1])
• sortiere die Elemente in den Körben per Heapsort und hänge die Körbe
• gesucht: aufsteigende Sortierung
hintereinander.
• wir stellen ein Verfahren vor, das eine Mischung aus einem speziellen
Beobachtung:
und einem allgemeinem Sortierverfahren darstellt.
• sei dkxi e < dkxj e
• dann folgt kxi + 1 ≤ dkxi e + 1 ≤ dkxj e < kxj + 1,
• also xi < xj
• somit sind die Körbe richtig geordnet
119 / 1
120 / 1
Sortierverfahren
Sortierverfahren
Beispiel:
Satz
• sortiere: 100 Schlüssel k1 , . . . , k100 aus natürlichen Zahlen im
(i) Die Laufzeit von Hybridsort ist im schlechtesten Fall O(n log n).
Intervall [1, 10.000]
(ii) Sind die xi unabhängig und gleichverteilt, so hat Hybridsort eine
mittlere Laufzeit von O(n).
• gesucht: aufsteigende Sortierung
• sei kmax = 1.000
• Division aller Schlüssel durch kmax ergibt xi aus (0, 1]
• sei α = 0.5
Beweis:
(i) die ersten beiden Schritte benötigen O(n)
• sei ti die Anzahl der Elemente im Korb i
P
• die Laufzeit der zweiten Phase beträgt höchstens O( ki=1 ti log ti ).
• dann ist k = dαne = d0.5 ∗ 100e = 50
• das Element xi = 0.98 landet dann im Korb dkxi e = d0.98 ∗ 50e = 49
• das Element xi = 0.13 landet dann im Korb dkxi e = d0.13 ∗ 50e = 7
• wegen
P
ti = n folgt
X
ti log ti ≤
X
ti log n ≤ n log n
• ...
und damit (i).
121 / 1
122 / 1
Sortierverfahren
Sortierverfahren
(ii) jedes einzelne xj ist mit Wahrscheinlichkeit 1/k in Korb i
• dann ist die Wahrscheinlichkeit, dass genau h Elemente im Korb
T
avg
i landen, gleich:
• der Anzahl der Möglichkeiten, h Elemente aus n auszuwählen,
mal
• der Wahrscheinlichkeit, dass diese Elemente im Korb i liegen,
und
h=2
Mit
• alle anderen nicht.
h
Somit:
Prob(ti = h) =
!
n 1 h
1
(n) ≤ k
h log h
( ) (1 − )n−h
h k
k
h=2
!
n
X
1
1
2 n
≤k
h
( )h (1 − )n−h .
h k
k
n
X
2
n
h
!
n 1 h
1
( ) (1 − )n−h .
h k
k
!
n!
(n − h)!h!
!
!
n−2
n−1
= n(n − 1)
+n
h−2
h−1
= (h(h − 1) + h)
=: A(n, h) + B(n, h)
Sei T avg (n) die erwartete Laufzeit von Hybridsort. Dann gilt:
T avg (n) ≤
k X
n
X
folgt:
h log h · Prob(ti = h)
T avg (n) ≤ k
i =1 h=2
«“ ” “
n „
X
1 h
1 ”n−h
A(n, h) + B(n, h)
1−
k
k
h=2
123 / 1
124 / 1
Sortierverfahren
Sortierverfahren
• B(n, h) = n n−1
h−1
• entsprechend folgt:
`
` ´
• A(n, h) = n(n − 1) n−2
h−2
` ´
P
• mit nh=0 nh ah b n−h = (a + b)n folgt:
n
X
n
X
“ 1 ”h “
1 ”n−h
A(n, h)
1−
k
k
h=2
!
n
X
n − 2 “ 1 ”h “
1 ”n−h
n(n − 1)
1−
h−2
k
k
h=2
!
n−2
X
1 ”n−2−h
n − 2 “ 1 ”h+2 “
n(n − 1)
1−
h
k
k
h=0
!
n−2
X
1
1 ”n−2−h
n − 2 “ 1 ”h “
n(n
−
1)
1
−
k2
k
k
h
h=0
„
«
n−2
1
1 “
1”
n(n − 1)
+ 1−
2
k
k
k
1
n(n − 1)
k2
=
=
=
=
=
h=2
n “
X
1 ”n−h
n − 1”“ 1 ”h “
1−
h−1 k
k
=
n
=
n “
X
n − 1”“ 1 ”h+1 “
1 ”n−1−h
1−
n
h
k
k
=
n
1 ”n−1−h
n X “n − 1”“ 1 ”h “
1−
k
h
k
k
h=1
h=1
=
=
=
Sortierverfahren
n
X
n
“ 1 ”h “
“ 1 ”h “
1 ”n−h X
1 ”n−h
A(n, h)
1−
+
B(n, h)
1−
k
k
k
k
h=2
h=2
|
{z
} |
{z
}
`
´n−1
= 1 n(n−1)
k2
“ 1 ”h “
1 ”n−h
1−
k
k
h=2
125 / 1
T avg (n) ≤ k
B(n, h)
´
= kn − kn 1− k1
“
“ k − 1 ”n−1 ”
n(n − 1)
=
+n 1−
k
k
“
“k − 1
”
”
n(n − 1)
≤
+n
(weil 1 −
)n−1 ≤ 1
k
k
n(n − 1)
≤
+n
(weil k ≥ αn)
α·n
= O(n).
127 / 1
n−1
X“
n − 1”“ 1 ”h “
1−
h
k
h=0
„
«
1 ” n−1
n 1 “
+ 1−
−
k k
k
n
n“
1 ”n−1
−
1−
k
k
k
n
k
1 ”n−1−h
n “n − 1”“ 1 ”0 “
1 ”n−1
−
1−
+0
0
k
k
k
k
n“
1 ”n−1
1−
k
k
126 / 1
Herunterladen