05.11.2012 Aufrufe

Optimale Sortieralgorithmen

Optimale Sortieralgorithmen

Optimale Sortieralgorithmen

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Optimale</strong> <strong>Sortieralgorithmen</strong><br />

Gerold Jäger<br />

12. Oktober 2003


Problem<br />

• Für n ∈ N sei S(n) die minimale Anzahl von Vergleichen,<br />

die benötigt wird, um n Elemente zu sortieren.<br />

• Bestimme S(n).<br />

S(n) ≤<br />

Obere Schranke<br />

� �<br />

n<br />

2<br />

= n(n − 1)<br />

2<br />

(ergibt sich aus dem trivialen Sortier-Algorithmus,<br />

bei dem man jedes Element mit jedem anderen<br />

vergleicht)<br />

1


Lineare Erweiterung<br />

Sei M = {1, · · · , n} und r eine Halbordnung auf M.<br />

Die Anzahl der möglichen Ordnungen O mit H ⊆ O<br />

bezeichnet man als lineare Erweiterung e(r).<br />

Beispiele: Man lasse die reflexiven Beziehungen weg.<br />

e(∅) = n!<br />

e((1, 2)) = n!<br />

2<br />

e((1, 2),(3, 4)) = n!<br />

4<br />

e((1, 2),(1, 3)) = n!<br />

3<br />

e((1, 2),(2, 3),(1, 3)) = n!<br />

6<br />

2


Untere Schranke<br />

Für 1 ≤ i �= j ≤ n und r ′ := r ∪ (i, j) und r ′′ :=<br />

r ∪ (j, i) gilt:<br />

e(r) = e(r ′ ) + e(r ′′ )<br />

Wegen e(∅) = n! und max{e(r ′ ),e(r ′′ )} ≤ e(r)<br />

2 folgt:<br />

S(n) ≥ ⌈log 2 n!⌉<br />

3


Algorithmus: binäres Einsortieren<br />

Seien die ersten k−1 Elemente schon sortiert. Das k-te<br />

Element ak wird einsortiert, indem man es mit einem<br />

mittleren Element aller noch nicht mit ak verglichenen<br />

Elemente vergleicht.<br />

Beispiel:<br />

1<br />

2<br />

3<br />

I III II<br />

Man benötigt ⌈log 2 k⌉ Schritte zum Einsortieren.<br />

4<br />

6<br />

5<br />

7<br />

8<br />

4


Algorithmus von Ford, Johnson<br />

(Verfeinerung des binären Einsortierens)<br />

• Vergleiche jeweils zwei neue Elemente, bis ein oder<br />

kein Element übrig ist.<br />

• Es ergeben sich zwei Gruppen. Für ungerades n<br />

nimm das übrige Element zur Gruppe der kleineren<br />

Elemente hinzu.<br />

• Sei n = 2m bzw. n = 2m + 1.<br />

• Sortiere die m größeren Elemente, indem man dieses<br />

Verfahren induktiv von n auf m überträgt.<br />

• Das Einsortieren der n − m kleineren Elemente geschieht<br />

auf folgende Weise (Beispiel n = 19):<br />

5


5<br />

6<br />

J<br />

7<br />

I<br />

8<br />

H<br />

9<br />

G<br />

3<br />

F<br />

Idee: Das Einsortieren in 2 k − 1 Elemente ist<br />

optimal.<br />

4<br />

E<br />

1<br />

D<br />

2<br />

C<br />

A<br />

B<br />

6


n US(n) S(n) FJ(n) BE(n)<br />

1 0 0 0 0<br />

2 1 1 1 1<br />

3 3 3 3 3<br />

4 5 5 5 5<br />

5 7 7 7 8<br />

6 10 10 10 11<br />

7 13 13 13 14<br />

8 16 16 16 17<br />

9 19 19 19 21<br />

10 22 22 22 25<br />

11 26 26 26 29<br />

12 29 30 30 33<br />

13 33 34 34 37<br />

14 37 38 38 41<br />

15 41 ? 42 45<br />

16 45 ? 46 49<br />

17 49 ? 50 54<br />

18 53 ? 54 59<br />

19 57 ? 58 64<br />

20 62 62 62 69<br />

21 66 66 66 74<br />

22 70 71 71 79<br />

23 75 ? 76 84<br />

24 80 ? 81 89<br />

25 84 ? 86 94<br />

47 198 ≤ 200 201 219<br />

7


Sortierbarkeits-Algorithmus<br />

Algorithmus SORT(r,c)<br />

EINGABE M = {1, · · · ,n}, r Halbord. auf M, c ∈ N<br />

(Algorithmus berechnet, ob r [insbesondere für r = ∅]<br />

in c Schritten sortierbar ist)<br />

1 IF e(r) ≤ 2<br />

2 RETURN Sortierbar<br />

3 FOR i = 1, · · · , n − 1<br />

4 FOR j = i + 1, · · · ,n<br />

5 IF (i, j) /∈ r AND (j,i) /∈ r<br />

6 r1 := r ∪ {(i, j)}<br />

7 r2 := r ∪ {(j, i)}<br />

8 IF e(r1) ≤ 2 c−1 AND e(r2) ≤ 2 c−1<br />

9 IF SORT(r1,c−1) AND SORT(r2, c−1)<br />

10 RETURN Sortierbar<br />

11 RETURN Nicht Sortierbar<br />

Nachteile:<br />

• rekursiver Algorithmus ⇒ sehr langsam<br />

• viele r1, r2 werden sowohl bei der Berechnung der<br />

Anzahl der linearen Erweiterungen als auch beim<br />

rekursiven Aufruf von SORT mehrfach getestet<br />

8


Wells Nicht-Sortierbarkeits-Algorithmus<br />

Algorithmus NON-SORT(r,c)<br />

EINGABE M = {1, · · · ,n}, r0 Halbord. auf M, c ∈ N<br />

(Algorithmus versucht zu beweisen, dass r0 insbesondere<br />

für r0 = ∅] nicht in c Schritten sortierbar ist)<br />

1 S0 = {r0}<br />

2 FOR k = 1, · · · , c<br />

3 Sk = ∅<br />

4 FOR EACH r ∈ Sc−1<br />

5 FOR i = 1, · · · , n − 1<br />

6 FOR j = i + 1, · · · ,n<br />

5 IF (i, j) /∈ r AND (j,i) /∈ r<br />

6 r1 := r ∪ {(i, j)}<br />

7 r2 := r ∪ {(j, i)}<br />

8 IF ! ISOM(r1, Sk) AND ! ISOM(r2, Sk)<br />

(Ist r1/r2 zu einem r ′ ∈ Sk isomorph?)<br />

9 IF e(r1) ≤ 2 c−k AND e(r2) ≤ 2 c−k<br />

10 IF e(r1) ≥ e(r2)<br />

11 Sk = Sk ∪ {r1}<br />

12 ELSE<br />

13 Sk = Sk ∪ {r2}<br />

9


14 IF Es gibt eine geordnete Menge in Sc<br />

15 Kein Ergebnis<br />

16 ELSE<br />

17 Nicht sortierbar<br />

Wells Algorithmus benötigt:<br />

Ullmans Algorithmus zum Aufspüren von Graphenisomorphismen<br />

Algorithmus zur Berechnung der Anzahl der linearen<br />

Erweiterungen<br />

Wells Algorithmus liefert:<br />

Für n = 12 ist r0 = ∅ nicht in 29 Schritten sortierbar.<br />

⇒ S(12) = 30<br />

10


Peczarskis Verbesserungen<br />

• Effizientere Implementation<br />

• Verbesserter Algorithmus zur Berechnung der Anzahl<br />

der linearen Erweiterungen<br />

• Neue Idee: Falls der Algorithmus kein Ergebnis liefert,<br />

kann man auf folgende Weise testen, ob auch<br />

in diesem Fall r0 nicht sortierbar ist:<br />

– Wende den Sortierbarkeits-Algorithmus für k =<br />

c − 1, · · · , 1 (soweit der Algorithmus Ergebnisse<br />

liefert) auf alle r ∈ Sk an.<br />

– Falls es ein k = c − 1, · · · , 1 gibt, so dass keine<br />

Menge aus Sk in c − k Schritten sortierbar ist,<br />

dann ist r0 nicht sortierbar.<br />

• Neue Ergebnisse:<br />

S(13) = 34,S(14) = 38,S(22) = 71<br />

11


Sortierbarkeit oder Nicht-Sortierbarkeit<br />

• Frage: Ist für n ∈ N r = ∅ in c Schritten sortierbar?<br />

• Notwendige Bedingung:<br />

e(r) = n! ≤ 2 c<br />

• Für k = 1, · · · , c muss nach dem k-ten Sortierschritt<br />

für die beiden möglichen neuen Halbordnungen r1<br />

und r2 mit e(r) = e(r1) + e(r2) gelten:<br />

max{e(r1), e(r2)} ≤ 2 c−k<br />

• Je größer der Quotient n!<br />

2 c ist, desto mehr kann man<br />

die Nicht-Sortierbarkeit erwarten und desto schneller<br />

ist der Nicht-Sortierbarkeits-Algorithmus fertig.<br />

12


Fälle, für die 2 mögliche S(n) in Frage<br />

kommen<br />

n 12 13 14 15 16 17<br />

n!<br />

2 ⌈log 2 n!⌉ 0.89 0.72 0.63 0.59 0.59 0.63<br />

n 18 19 22 23 24<br />

n!<br />

2 ⌈log 2 n!⌉ 0.71 0.84 0.95 0.68 0.51<br />

Berechnung weiterer Werte von S(n)<br />

• Wells und Peczarskis Nicht-Sortierbarkeits-<br />

Algorithmus liefert nur negative Resultate:<br />

– S(12) > 29 ⇒ S(12) = 30 (Wells)<br />

– S(13) > 33 ⇒ S(13) = 34 (Peczarski)<br />

– S(14) > 37 ⇒ S(14) = 38 (Peczarski)<br />

– S(22) > 70 ⇒ S(22) = 71 (Peczarski)<br />

• Vermutung: S(16) = 45 < 46 = FJ(16)<br />

• Solche verbesserten Algorithmen können nur mit<br />

dem (zu langsamen) Sortierbarkeits-Algorithmus<br />

nachgewiesen werden.<br />

⇒ Verbesserter Sortierbarkeits-Algorithmus!<br />

13


Verbesserter Sortierbarkeits-Algorithmus<br />

Algorithmus NEW-SORT(r,c)<br />

EINGABE M = {1, · · · ,n}, r Halbord. auf M, c ∈ N<br />

(Algorithmus berechnet, ob r [insbesondere für r = ∅]<br />

in c Schritten sortierbar ist)<br />

Ideen des Algorithmus<br />

• Man betrachte c Stufen 0, · · · , c − 1.<br />

• In Stufe k betrachte man Halbordnungen, die in<br />

c − k Schritten sortierbar sind.<br />

• Für jede Halbordnung r ′ in jeder Stufe k gibt es drei<br />

Zustände:<br />

sortierbar=2, nicht sortierbar=1, undefiniert=0.<br />

• Zum Durchführen von Isomorphietests und somit<br />

zum Vermeiden doppelter Berechnungen speichern<br />

wir alle Zwischenergebnisse der Art:<br />

14


′ (in Stufe k) ist in c − k Schritten (nicht)<br />

sortierbar.<br />

• Stufe 0 hat am Anfang den Zustand 0. Hat diese<br />

Stufe den Zustand 2, so ist r sortierbar. Hat sie den<br />

Zustand 1, so ist r nicht sortierbar.<br />

• Wir benutzen folgende Beobachtung:<br />

r ′ ist in k Schritten sortierbar.<br />

⇔ Es gibt 1 ≤ i < j ≤ n, so dass r ′ ∪ {(i, j)}<br />

und r ′ ∪ {(j, i)} in k − 1 Schritten sortierbar sind<br />

• In jeder Stufe außer 0 werden zwei Halbordnungen<br />

betrachtet.<br />

15


• Folgende Zustände sind denkbar:<br />

a) (0, 0) oder (2,0) (bzw. (0) in Stufe 0)<br />

∗ Erhöhe die Stufe um 1.<br />

∗ Addiere zu r ′ aus der letzten Stufe ein noch<br />

nicht betrachtetes Paar (i, j).<br />

∗ Mögliche Zustände in der neuen Stufe:<br />

· (0,0): Keine Informationen.<br />

· (1,0), (2,0), (2, 1),(2, 2): Informationen durch<br />

Isomorphietests.<br />

b) (1, 0) oder (2,1)<br />

∗ Verringere die Stufe um 1.<br />

∗ Mögliche Zustände in der neuen Stufe:<br />

· (0,0), (2,0): Man kann noch weitere Paare<br />

testen.<br />

· (1,0), (2,1) (bzw. (1) in Stufe 0): Man hat<br />

alle Paare getestet.<br />

c) (2, 2)<br />

∗ Verringere die Stufe um 1.<br />

∗ Mögliche Zustände in der neuen Stufe:<br />

· (2,0): Man muss noch das umgekehrte Paar<br />

testen.<br />

16


· (2,2) (bzw. (2) in Stufe 0): Man hat beide<br />

Paare getestet.<br />

d) (0, 1), (0,2)<br />

· Nicht möglich, da definitionsgemäß das erste<br />

Paar immer zuerst betrachtet wird.<br />

e) (1, 1), (1,2)<br />

· Nicht möglich, da wenn ein Paar keine sortierbare<br />

Halbordnung liefert, das umgekehrte<br />

Paar nicht mehr betrachtet werden muss.<br />

• Weiter wird benutzt, dass eine Halbordnung r ′ in<br />

1 Schritt sortierbar ist, genau dann wenn e(r ′ ) ≤ 2<br />

ist.<br />

Vorteile im Vergleich zum<br />

Original-Algorithmus<br />

• Nicht-rekursiver Algorithmus.<br />

• Durch Isomorphietests Vermeiden von doppelten<br />

Rechnungen.<br />

17

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!