• Keine Ergebnisse gefunden

Universität Bremen

N/A
N/A
Protected

Academic year: 2022

Aktie "Universität Bremen"

Copied!
4
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

1

Universität Bremen

Sortieren

Thomas Röfer

Permutationen Naives Sortieren Sortieren durch Einfügen, Auswählen, Vertauschen, Mischen QuickSort Comparator

2

Universität Bremen

PI-2: Sortieren

Identität/Flache/Tiefe Gleichheit

Rückblick „Suchen“

11 11 a b

22nullnull 22nullnull 111

1 111 1 a b

222nullnull 2 nullnull 222nullnull 2 nullnull

Binäre Suche

1 5 8 9 11 1 5 8 9 11 1 5 8 9 11

Lineare Suche

1 5 8 9 11

3 1 6 5 3

1 0 3 3 2

0 0 1 2 1

I(n) M(n) V(n) Z(n)

10 9 8 7 6 5

45 36 55 47

36 28 45 38

28 21 36 30

21 15 28 23

15 10 21 17

10 6 15 12

6 3 10 8

45 36 55 47

36 28 45 38

28 21 36 30

21 15 28 23

15 10 21 17

10 6 15 12

6 3 10 8 4

Aufwand Asymptotische Komplexität Typische Aufwandsklassen

O(1) : swap() O(log n) : binarySearch() O(n) : linearSearch() O(n log n) : mergeSort() O(n²) : selectSort() O(n!) : naiveSort() O(1) : swap() O(log n) : binarySearch() O(n) : linearSearch() O(n log n) : mergeSort() O(n²) : selectSort() O(n!) : naiveSort()

3

Universität Bremen

PI-2: Sortieren

Permutieren nach Dijkstra

Ziel

Eine Funktion, die aus einer gegebenen Permutation die jeweils nächste erzeugt

Voraussetzung: Es existiert eine Ordnungsrelation zwischen den Elementen der zu permutierenden Folge

Algorithmus Folge a

0

… a

n-1

Finde das letzte a

i

, das kleiner als a

i+1

ist Finde das letzte a

j

, das größer als a

i

ist Vertausche die beiden

Drehe die Reihenfolge der Elemente ab a

i+1

um Aufwand

Im Mittel O(1)

im Mittel werden nur 1,76 Elemente durchsucht und umgedreht

4

Universität Bremen

PI-2: Sortieren

Permutieren nach Dijkstra

2 3 1 4

2 3 4 1 2 3

4 1

2 4 3 1 2 4

1 3

2 4 3 1 2 4

3 1

3 4 2 1 3 1

2 4

3 1 4 2

5

Universität Bremen

PI-2: Sortieren

Permutieren nach Dijkstra

class Permutation {

static void nextPerm(Comparable[] a) {

int i;

for(i = a.length - 2; i >= 0 &&

a[i].compareTo(a[i+1]) >= 0; --i)

; if(i >= 0) {

int j;

for(j = a.length - 1;

a[j].compareTo(a[i]) <= 0; --j)

; swap(a, i, j);

}

reverse(a, i + 1, a.length - 1);

} classPermutation {

staticvoidnextPerm(Comparable[] a) {

inti;

for(i = a.length - 2; i >= 0 &&

a[i].compareTo(a[i+1]) >= 0; --i)

; if(i >= 0) {

intj;

for(j = a.length - 1;

a[j].compareTo(a[i]) <= 0; --j)

; swap(a, i, j);

}

reverse(a, i + 1, a.length - 1);

}

static private void reverse(

Comparable[] a, int l, int r) {

while(l < r) swap(a, l++, r--);

}

static void swap(Object[] o, int a, int b)

{

Object temp = o[a];

o[a] = o[b];

o[b] = temp;

} }

static privatevoidreverse(

Comparable[] a, intl, intr) {

while(l < r) swap(a, l++, r--);

}

staticvoidswap(Object[] o, inta, intb)

{

Object temp = o[a];

o[a] = o[b];

o[b] = temp;

} }

6

Universität Bremen

PI-2: Sortieren

Sortieren

Definition

Eine sortierte Folge Sist eine Permutationeiner Folge T S = perm(T)

Sbezeichnet man als aufsteigend sortiert, wenn jedes Element größer oder gleich seinem Vorgänger in der Folge ist

s0≤s1≤... ≤sn-1

Sbezeichnet man als absteigendsortiert, wenn jedes Element kleiner oder gleich seinem Vorgänger in der Folge ist

s0≥s1≥... ≥sn-1

Sortierkriterium

Es wird immer nach einem Sortierkriterium sortiert (Sortierschlüssel) Der Sortierschlüssel kann sich aus mehreren Teilen zusammensetzen

z.B. Name, Vorname, Telefonnummer

Je komplexer der Sortierschlüssel, desto komplexer die zum Sortieren notwendigen Vergleiche

Indizes

Zu einer Menge von Daten können mehrere sortierte Indizesvorgehalten werden

(2)

2

7

Universität Bremen

PI-2: Sortieren

Naives Sortieren

Algorithmus

Erzeuge so lange Permutionen, bis eine entsprechend dem Kriterium sortiert ist

Aufwand

Bester Fall: O(n)

vorsortiert Schlechtester Fall:

O(½ n · n!) = O(n · n!) erst letzte Permutation ist sortiert Nicht-Sortiertheit wird im Mittel nach der Hälfte der Vergleiche festgestellt Durchschnittlicher Fall:

O(½ n · n! / 2) = O(n · n!) Sortierte Folge wird nach der Hälfte der Permutationen gefunden Nicht-Sortiertheit wird im Mittel nach der Hälfte der Vergleiche festgestellt

static void naiveSort(

Comparable[] a) {

while(!sorted(a)) Permutation.nextPerm(a);

}

static private boolean sorted(

Comparable[] a) {

for(int i = 1; i < a.length;

++i)

if(a[i].compareTo(a[i-1]) < 0) return false;

return true;

}

staticvoidnaiveSort(

Comparable[] a) {

while(!sorted(a)) Permutation.nextPerm(a);

}

static privatebooleansorted(

Comparable[] a) {

for(inti = 1; i < a.length;

++i)

if(a[i].compareTo(a[i-1]) < 0) returnfalse;

returntrue;

}

8

Universität Bremen

PI-2: Sortieren

Sortieren durch Einfügen

5 2 3 1 4

5

5 2 3 1 4

5 2 3 1 4

5 2 3 1 4

5 2 3 1 4

2 5 2 3 5 1 2 3 5 1 2 3 4

5

9

Universität Bremen

PI-2: Sortieren

Sortieren durch Einfügen

Algorithmus

Füge alle Elemente der Reihe nach in eine ursprünglich leere Folge sortiert ein

Problem bei Reihungen: Einfügen heißt, dass alle Elemente hinter der Einfügeposition verschoben werden müssen

Aufwand

Doppelter Speicherplatzverbrauch Bester Fall: O(n)

vorsortiert Schlechtester Fall: O(n²)

rückwärts sortiert Durchschnittlicher Fall:

O(½n²) = O(n²)

Einsortieren im Mittel in der Mitte

static void insertSort(Comparable[] a) {

Comparable[] b = (Comparable[]) a.clone();

for(int i = 0; i < b.length; ++i) {

int j = i;

while(j > 0 &&

a[j - 1].compareTo(b[i]) > 0) {

a[j] = a[j - 1];

--j;

} a[j] = b[i];

} }

staticvoidinsertSort(Comparable[] a) {

Comparable[] b = (Comparable[]) a.clone();

for(inti = 0; i < b.length; ++i) {

intj = i;

while(j > 0 &&

a[j - 1].compareTo(b[i]) > 0) {

a[j] = a[j - 1];

--j;

} a[j] = b[i];

} }

10

Universität Bremen

PI-2: Sortieren

Sortieren durch Auswählen

5 2 3 1 4

1 2 3 4 5

2 5 3 1 4

1 5 3 2 4

1 2 5 3 4

1 2 3 5 4

1 3 5 2 4

11

Universität Bremen

PI-2: Sortieren

Sortieren durch Auswählen

Algorithmus

Falls nur noch ein Element übrig ist, ist die Folge sortiert.

Ansonsten

Suche nach dem kleinsten Element und stelle es an den Anfang, sortiere den Rest.

Aufwand

In jedem Durchgang wird ein Element ausgewählt Um das Element auszuwählen, müssen im Mittel n/2 Elemente durchsucht werden Durchschnittlicher Fall:

O(

½

n · n) = O(

½

n2) = O(n2)

static void selectSort(Comparable[] a) {

for(int i = 0; i < a.length - 1; ++i) for(int j = i + 1; j < a.length; ++j)

if(a[i].compareTo(a[j]) > 0) swap(a, i, j);

}

static void swap(Object[] o, int a, int b) {

Object temp = o[a];

o[a] = o[b];

o[b] = temp;

}

staticvoidselectSort(Comparable[] a) {

for(inti = 0; i < a.length - 1; ++i) for(intj = i + 1; j < a.length; ++j)

if(a[i].compareTo(a[j]) > 0) swap(a, i, j);

}

staticvoidswap(Object[] o, inta, intb) {

Object temp = o[a];

o[a] = o[b];

o[b] = temp;

}

12

Universität Bremen

PI-2: Sortieren

BubbleSort

5 2 3 1 4

2 5 3 1 4

2 3 5 1 4

2 3 1 5 4

1 2 3 4 5

1 2 3 4 5 2 3 1 4 5

2 3 1 4 5

2 1 3 4 5

2 1 3 4 5

(3)

3

13

Universität Bremen

PI-2: Sortieren

BubbleSort

Algorithmus

Gehe der Reihe nach durch alle Elemente und vertausche zwei jeweils aufeinander folgende, wenn ihre Reihenfolge falsch ist Wiederhole dies so lange, bis keine Vertauschungen mehr notwendig sind

Aufwand

Günstigster Fall: O(n) vorsortiert Schlechtester Fall: O(n²)

rückwärts sortiert (maximale Anzahl von Vertauschungen) Durchschnittlicher Fall: O(n²) im Mittel ½ n² Vertauschungen

static void bubbleSort(Comparable[] a) {

boolean swapped;

do {

swapped = false;

for(int j = 1; j < a.length; ++j) if(a[j].compareTo(a[j - 1]) < 0) {

swap(a, j, j - 1);

swapped = true;

} }

while(swapped);

}

staticvoidbubbleSort(Comparable[] a) {

booleanswapped;

do {

swapped = false;

for(intj = 1; j < a.length; ++j) if(a[j].compareTo(a[j - 1]) < 0) {

swap(a, j, j - 1);

swapped = true;

} }

while(swapped);

}

14

Universität Bremen

PI-2: Sortieren

Sortieren durch Mischen

5 2 3 1 4

5 2 3

1 4

5 2 3 1

4

1 4

1 2 3 4

5

1 1 2

1 4 1 44

3

5 2 2 5 5 1 3 3 4 4

15

Universität Bremen

PI-2: Sortieren

Sortieren durch Mischen

Algorithmus

Enthält die Folge kein oder nur ein Element, ist sie sortiert Ansonsten

Teile die Folge in zwei gleich große Hälften Sortiere die Hälften

Mische die sortierten Hälften wieder zusammen

Mischen

Vergleiche die beiden ersten Elemente der Hälften

Entnimm das kleinere von beiden und füge es dem Ergebnis hinzu Wiederhole so lange, bis beide Hälften leer sind

Aufwand

Folge kann log2(n) mal in Hälften zerlegt werden

Auf jeder Ebene der Zerlegung werden alle Elemente einmal gemischt: O(n) Insgesamt (in jedem Fall): O(nlog n)

Platzkomplexität: 2 nElemente beim Mischen

16

Universität Bremen

PI-2: Sortieren

Sortieren durch Mischen

static Queue mergeSort(Queue q) {

if(q.length() > 1) {

Queue q2 = new Queue();

balance(q, q2);

return merge(mergeSort(q), mergeSort(q2));

} else

return q;

}

staticQueue mergeSort(Queue q) {

if(q.length() > 1) {

Queue q2 = newQueue();

balance(q, q2);

returnmerge(mergeSort(q), mergeSort(q2));

} else

returnq;

}

static private void balance(Queue q1, Queue q2) {

while(q1.length() > q2.length()) q2.push(q1.pop());

}

static private Queue merge(Queue q1, Queue q2) {

Queue q = new Queue();

while(q1.length() > 0 || q2.length() > 0) if(q2.length() == 0 || q1.length() > 0

&& ((Comparable) q1.top()) .compareTo(q2.top()) < 0) q.push(q1.pop());

else

q.push(q2.pop());

return q;

}

static privatevoidbalance(Queue q1, Queue q2) {

while(q1.length() > q2.length()) q2.push(q1.pop());

}

static privateQueue merge(Queue q1, Queue q2) {

Queue q = newQueue();

while(q1.length() > 0 || q2.length() > 0) if(q2.length() == 0 || q1.length() > 0

&& ((Comparable) q1.top()) .compareTo(q2.top()) < 0) q.push(q1.pop());

else

q.push(q2.pop());

returnq;

} classQueue

{

voidpush(Object) … Object pop() … Object top() … intlength() … }

17

Universität Bremen

PI-2: Sortieren

QuickSort

3 2 5 1 4

3

2 5

1 4

2 5

1 4

1 4

18

Universität Bremen

PI-2: Sortieren

QuickSort – Ungünstige Vorsortierung

1 2 3 4 5

1 2

3 4 5

1 2 3

4 5

1 2 3 4 5

1 2 3 4 5

1 2 3 4 5

(4)

4

19

Universität Bremen

PI-2: Sortieren

QuickSort

Algorithmus

Enthält die Folge kein oder nur ein Element, ist sie sortiert Ansonsten

entnimm ein Element,

bilde eine neue Liste aus allen kleineren Elementen und lasse diese sortieren, bilde eine neue Liste aus allen größeren Elementen und lasse diese sortieren,

Hänge die sortierte Liste der kleineren Elemente, das gewählte Element und die sortierte Liste der größeren Elemente aneinander und liefere diese zurück.

Aufwand

Günstigster Fall: O(nlog n) beide Teillisten sind jeweils gleich lang Schlechtester Fall: O(n2)

Eine der Teillisten ist immer leer

Wenn als Pivot-Element immer das erste verwendet wird, ist dies bei Vorsortierung der Fall!

Durchschnittlicher Fall: O(nlog n) Beweis siehe Ottmann / Widmayer

Kein zusätzlicher Speicherbedarf bei Sortierung eines Arrays!

20

Universität Bremen

PI-2: Sortieren

QuickSort einer Warteschlange

static void quickSort(Queue q) {

if(q.length() > 0) {

Comparable pivot = (Comparable) q.pop();

Queue q1 = new Queue(), q2 = new Queue();

split(q, pivot, q1, q2);

quickSort(q1);

quickSort(q2);

join(q, pivot, q1, q2);

} }

staticvoidquickSort(Queue q) {

if(q.length() > 0) {

Comparable pivot = (Comparable) q.pop();

Queue q1 = new Queue(), q2 = new Queue();

split(q, pivot, q1, q2);

quickSort(q1);

quickSort(q2);

join(q, pivot, q1, q2);

} }

static void split(Queue q, Comparable pivot, Queue q1, Queue q2) {

while(q.length() > 0) if(pivot.compareTo(q.top()) > 0)

q1.push(q.pop());

else

q2.push(q.pop());

}

static void join(Queue q, Object pivot, Queue q1, Queue q2) {

while(q1.length() > 0) q.push(q1.pop());

q.push(pivot);

while(q2.length() > 0) q.push(q2.pop());

}

staticvoidsplit(Queue q, Comparable pivot, Queue q1, Queue q2) {

while(q.length() > 0) if(pivot.compareTo(q.top()) > 0)

q1.push(q.pop());

else

q2.push(q.pop());

}

staticvoidjoin(Queue q, Object pivot, Queue q1, Queue q2) {

while(q1.length() > 0) q.push(q1.pop());

q.push(pivot);

while(q2.length() > 0) q.push(q2.pop());

}

21

Universität Bremen

PI-2: Sortieren

QuickSort mit Arrays

7 4 1 9 0 2 5 4 8 3

7

7 4 1 3 0 2 5 4 8 9

4 4 1 3 0 2 5 7 8 9

quickSort quickSort

22

Universität Bremen

PI-2: Sortieren

QuickSort

static private void quickSort2(Comparable[] a, int bottom, int top) {

if(bottom + 1 < top) {

swap(a, bottom, (top + bottom) / 2);

Comparable pivot = a[bottom];

int i = bottom + 1, j = top - 1;

do {

while(i < top && a[i].compareTo(pivot) < 0) ++i;

while(j > bottom && a[j].compareTo(pivot) >= 0) --j;

if(i < j) swap(a, i, j);

} while(i < j);

swap(a, i - 1, bottom);

quickSort2(a, bottom, i - 1);

quickSort2(a, i, top);

} }

static privatevoidquickSort2(Comparable[] a, intbottom, inttop) {

if(bottom + 1 < top) {

swap(a, bottom, (top + bottom) / 2);

Comparable pivot = a[bottom];

inti = bottom + 1, j = top - 1;

do {

while(i < top && a[i].compareTo(pivot) < 0) ++i;

while(j > bottom && a[j].compareTo(pivot) >= 0) --j;

if(i < j) swap(a, i, j);

} while(i < j);

swap(a, i - 1, bottom);

quickSort2(a, bottom, i - 1);

quickSort2(a, i, top);

} }

static void quickSort(Comparable[] a) {

quickSort2(a, 0, a.length);

}

staticvoidquickSort(Comparable[] a) {

quickSort2(a, 0, a.length);

}

23

Universität Bremen

PI-2: Sortieren

Schnittstelle Comparator

Motivation

Die Schnittstelle Comparable legt nur genau eine Ordnungsrelation für eine Klasse fest Die Schnittstelle Comparator erlaubt die Definition beliebiger weiterer Ordnungsrelationen

Anonyme Klassen

Java erlaubt die „Am Ort Ableitung“

Dabei wird gleichzeitig eine namenlose Klasse vereinbart und ein einziges Objekt von ihr erzeugt Angegeben wird nur die Basisklasse oder eine Schnittstelle

import java.util.Comparator;

static void selectSort(Object[] a, Comparator c) {

for(int i = 0; i < a.length - 1; ++i) for(int j = i + 1; j < a.length; ++j)

if(c.compare(a[i],a[j]) > 0) swap(a, i, j);

}

static void selectSort(String[] s) {

selectSort(s, new Comparator() {

public int compare(Object a, Object b) {

return ((String) a).compareTo(b);

} });

}

importjava.util.Comparator;

staticvoidselectSort(Object[] a, Comparator c) {

for(inti = 0; i < a.length - 1; ++i) for(intj = i + 1; j < a.length; ++j)

if(c.compare(a[i],a[j]) > 0) swap(a, i, j);

}

staticvoidselectSort(String[] s) {

selectSort(s, newComparator() {

publicintcompare(Object a, Object b) {

return((String) a).compareTo(b);

} });

}

Referenzen

ÄHNLICHE DOKUMENTE

[r]

Auch der Nachbarshund Die Kinder sind draußen im Garten ruft die Mutter die Kinder hereinI. denn jeder will zuerst

Der Mann läuft dem Hund nach.. Gerhard passt auf seine Schwester

Die Anzahl Sortierschlüssel lässt sich indirekt noch erhöhen, in dem beispielsweise die Angaben für den Beruf (mit L als Sortierkürzel für Lehrperson) und für das Geschlecht (w

(3) Anfragen, die innerhalb einer Sitzung des Gremiums gestellt und nicht unmittelbar beantwortet werden können, sind innerhalb von drei Wochen zu beantworten, ansonsten

(9) Nach Ablauf der Frist des Absatzes 8 sind die schriftlichen Habilitationsleistungen, die Gutach- ten und ggf. die Stellungnahme des Bewerbers oder der Bewerberin vier Wochen

[r]

(4) Werden einer Kommission oder einem Ausschuss durch Beschluss des Akademischen Se- nats oder allgemein durch Satzung Entscheidungsbefugnisse übertragen, die die Lehre betreffen,