• Keine Ergebnisse gefunden

Suchen und Sortieren

N/A
N/A
Protected

Academic year: 2021

Aktie "Suchen und Sortieren"

Copied!
39
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Suchen und Sortieren

OOPM, Ralf Lämmel

Unterhaltet Euch mal mit Euren Großeltern wie Sortieren

früher funktionierte!

(2)

Das Such-Problem

Eingabe:

Ein Feld a mit n Elementen vom Typ t.

Ein Wert x vom Typ t.

Ausgabe:

Ein Boolescher Wert:

true: Es gibt ein 0 <= i < n so dass a[i] == x false: sonst

Wir nehmen nichts weiter an als dass wir Gleichheit für t

bestimmen können.

(3)

Lineare Suche (Index-Rückgabe)

public static int linear(int[] a, int x) { for (int i=0; i<a.length; i++)

if (a[i] == x) return i;

return -1;

}

Beachte: eine For-Each-

Schleife wäre hier nicht (sinnvoll) anwendbar, da wir i zurückgeben

wollen!

Siehe package algorithm.search

(4)

Binäre Suche

Basierend auf der Annahme, dass das Eingabefeld (etwa aufsteigend) sortiert ist, beginnend in der Mitte des Feldes, suche das Element mittels Halbierung des Suchraums in jedem Schritt.

Die Suche beginnt mit i = Mitte.

Wenn a[i] = x, dann gefunden.

Wenn a[i] < x, dann in rechter Hälfte fortsetzen.

Wenn a[i] > x, dann in linker Hälfte fortsetzen.

(5)

Testen der Sortiertheit

Beispiel 1:

Eingabe: {1,2,3,4}

Ausgabe: true

Beispiel 2:

Eingabe: {1,3,2,4}

Ausgabe: false

(6)

Das Problem

des Testens der Sortiertheit

Eingabe:

Ein Feld a mit n Elementen vom Typ t.

Ausgabe:

Ein Boolescher Wert:

true: a[i-1] <= a[i] für alle i mit 1 <= i < n

http://www.bambinipronto.com.au/

(7)

Probleme: Kontenverwaltung, Videokompression, ...

Programme: (Effektive) Problemlösungen

Spezifikationen: (“Gute”) Problembeschreibungen Modelle: Abstraktionen von Problemlösungen u.a.

Ist diese Problembeschreibung eine Spezifikation, ein Modell oder

ein Programm?

Eingabe:

Ein Feld a mit n Elementen vom Typ t.

Ausgabe:

Ein Boolescher Wert:

true: a[i-1] <= a[i] für alle i mit 1 <= i < n

false: sonst

(8)

Sortiertheitstest

public static boolean isSorted(int[] a) { for (int i=1; i<a.length; i++)

if (a[i-1] > a[i])

return false; // inversion found

return true; // no inversion found

}

(9)

Binäre Suche

public static int binary(int[] a, int x) { int first = 0; // first index in range

int last = a.length - 1; // last index in range while (first <= last) {

int middle = first + ((last - first) / 2);

if (a[middle] < x) {

first = middle + 1; // go to the right } else if (a[middle] > x) {

last = middle - 1; // go to the left } else

return middle;

}

return -1; // not found

} Siehe package algorithm.search

(10)

Zusammenfassung:

Einfache Suchalgorithmen

Dimensionen der Variationen:

Effizienz (Laufzeit-Komplexität)

Annahmen über Eigenschaften des Feldes

Annahmen über Operationen (Gleichheitstest, etc.)

(11)

Das Sortier-Problem

2

3 5

7

Eine unsortierte Liste

2 3 5 7

Die sortierte Liste

(12)

Das Sortier-Problem

Eingabe: Ein Feld a mit n Elementen des Typs t Annahme: Vergleichbarkeit (<,=) für Typ t

Ausgabe:

Ein Feld b

b ist sortiert.

b ist eine Permutation von a

Beachte: Dies ist eine

Problembeschreibung (im

Gegensatz zu einer Lösung).

(13)

Permutationstest

Eingabe: Feld a und b gleicher Länge

Annahme: Gleicheitstest für Typ t verfügbar.

Ausgabe:

Gibt es eine 1:1 Abbildung von a auf b?

Ausgangs- und Bildelement sind jeweils gleich.

1 3 2

3

1

2

(14)

Permutationstest

// Assume all elements of the arrays to be distinct

public static boolean isPermutation(int[] a, int[] b) { if (a.length != b.length)

return false;

for (int x : a) {

boolean found = false;

for (int y : b) if (x == y) {

found = true;

break;

}

if (!found)

return false;

Dies kann wesentlich eleganter beschrieben werden wenn wir Label-basiertes Break/Continue

verwenden.

Vorbedingung

(15)

Permutationstest

(kompaktere Variante)

// Assume all elements of the arrays to be distinct

public static boolean isPermutation(int[] a, int[] b) { if (a.length != b.length)

return false;

l1: for (int x : a) { for (int y : b)

if (x == y)

continue l1;

return false;

}

return true;

}

Wie lässt sich diese Annahme aufgeben?

Siehe package algorithm.sorting

(16)

Verallgemeinerter Permutationsansatz

Eingabe: Felder a und b gleicher Länge l.

Ausgabe: Boolescher Wert

“Ist a eine Permutation von b?”

(Eine mögliche) Vorgehensweise:

Initialisiere ein Boolesches Feld c der Länge l mit false.

Für jedes Element x von a

Gibt es einen Index i mit x == b[i] und c[i] == false?

- Ja: Setze c[i] = true.

- Nein: Gib false zurück.

(17)

Verallgemeinerter Permutationsansatz

public static boolean isPermutation(int[] a, int[] b) { if (a.length != b.length)

return false;

boolean[] c = new boolean[a.length];

for (int i=0; i<c.length; i++) c[i] = false;

l1: for (int x: a) {

for (int i = 0; i < b.length; i++) if (x==b[i] && !c[i]) {

c[i] = true;

continue l1;

}

return false;

} }

Fangfrage:

Können wir an dieser Stelle stattdessen eine Methode für etwa lineare

Suche in b wiederverwenden?

Siehe package algorithm.sorting

(18)

Warum Sortieren in OOPM?

Grundlegende Technik in der Programmierung Hervorragende Eignung für weitere Themen:

Laufzeitanalyse (Laufzeitkomplexität)

Speicherplatzanalyse (Speicherkomplexität) Iterative vs. rekursive Lösungen

Verifikation

(19)

Ausgewählte Sortierverfahren

BubbleSort -- Sortieren durch Sprudeln

SelectionSort -- Sortieren durch Auswahl

InsertionSort -- Sortieren durch Einfügen

MergeSort -- Sortieren durch Mischen

(20)

Ausgabe eines Feldes (Gut zum visuellen Testen!)

Beispiel

Eingabe: {1,2,3,4}

Ausgabe: 1 2 3 4 (in der “Standardausgabe”)

(21)

Ausgabe eines Feldes

public static void print(int[] a) { for (int i=0; i<a.length; i++)

System.out.print(a[i] + " ");

System.out.println();

}

Siehe package data.vector

Eingabe: {1,2,3,4}

Ausgabe: 1 2 3 4 (in der “Standardausgabe”)

(22)

Der Ergebnistyp void

void ist ein spezieller vordefinierter Typ.

void ist formal ein Menge mit einem Element.

Verwendung:

Funkion berechnet keine Ergebnisse.

Beispiele: Mutationen, Ausgaben

(23)

BubbleSort - Beispiel

Inversionen benachbarter Elemente sind markiert.

★ 1.Runde 8 2 4 9 7 2 8 4 9 7 2 4 8 9 7 2 4 8 9 7

★ 2.Runde 2 4 8 7 9 2 4 8 7 9 2 4 8 7 9 2 4 7 8 9

★ 3.Runde 2 4 7 8 9 2 4 7 8 9 2 4 7 8 9 2 4 7 8 9

9 ist nach oben

“gebubbelt”.

Warum haben wir eine 3. Runde?

(24)

BubbleSort - Vorgehensweise

Wiederhole Pässe durch die Eingabe.

Beseitige Inversionen benachbarter Elemente.

Brich ab nach einem Pass ohne Inversionen.

Folgerung: Große Elemente “bubbeln” nach oben.

(25)

BubbleSort - Implementation

public static void bubbleSort(int[] a) {

boolean swapped; // to notice swaps during a pass do {

swapped = false;

for (int i=1; i<a.length; i++) if (a[i-1] > a[i]) {

// Swap!

int swap = a[i];

a[i] = a[i-1];

a[i-1] = swap;

swapped = true;

}

} while (swapped); // another pass if swaps happened

} Siehe package algorithm.sorting

(26)

SelectionSort - Beispiel

8 2 4 9 7

2 4 7 8 9

2 4 7 8 9

2 4 7 9 8

2 4 8 9 7

2 8 4 9 7

Zeitachse

(27)

SelectionSort - Vorgehensweise

Entferne kleinstes Element x aus Eingabe.

Füge x der Ausgabe zu.

Wiederhole Schritte bis die Eingabe leer ist.

Folgerung: Ausgabe entsteht linear.

(28)

SelectionSort - Implementation

public static void selectionSort(int[] a) { for (int i=0; i<a.length; i++) {

// Find least element among the remaining ones int least = i;

for (int j=i+1; j<a.length; j++) if (a[j] < a[least])

least = j;

// Swap current element with least one if (least != i) {

int swap = a[i];

a[i] = a[least];

a[least] = swap;

(29)

InsertionSort - Beispiel

8 2 4 9 7

2 4 7 8 9

2 4 8 9 7

2 4 8 9 7

2 8 4 9 7

8 2 4 9 7

Zeitachse

(30)

InsertionSort - Vorgehensweise

Unterteilung

sortierter Präfix (anfangs leer)

unsortierter Rest (anfangs die Eingabe) Wiederholung

Einfügen des Kopfes vom Rest in den Präfix

(31)

InsertionSort - Implementation

public static void insertionSort(int[] a) { for (int i=1; i<a.length; i++) {

int x = a[i]; // Element to be inserted // Insert elements in their prefix

// Shift right elements if necessary int j = i;

while (j > 0 && a[j-1] > x) { a[j] = a[j-1];

a[j-1] = x;

j--;

} }

} Siehe package algorithm.sorting

(32)

MergeSort

Merge

Rekursives Sortieren

Linke Hälfte Rechte Hälfte

Zwischenergbnis

Teilung der Eingabe

Zwischenergbnis

Sortiertes Ergebnis

(33)

MergeSort - Beispiel

8 2 4 9 7

8 2 4 9 7

8 2 4 9 7

7

9 9 7

7 9 2 4

8

4 7 9 2 8

2 4 7 8 9

commons.wikimedia.org

commons.wikimedia.org

(34)

Mischen

2 8 4 7 9

2 4 7 8 9

(35)

MergeSort - Implementation

public static void mergeSort(int[] a, int[] temp, int min, int max) { // Cease on trivial sorting problem

if (!(min<max)) return;

// Divide

int middle = ( min + max ) / 2 ;

// Solve smaller problems recursively mergeSort(a,temp,min,middle);

mergeSort(a,temp,middle+1,max);

// Merge via temporary array merge(a,temp,min,middle,max);

} Siehe package algorithm.sorting

(36)

Merge - Implementation

public static void merge(int[] a, int[] temp, int min, int middle, int max) { int i = min; // loop over left half

int j = middle+1; // loop over right half int k = min; // loop over merged result while (k<=max)

temp[k++] = (i <= middle && (j > max || a[i] < a[j])) ? a[i++] // copy from left half

: a[j++]; // copy from right half

// Commit temporary result

for (k=min; k<=max; k++)

(37)

Fangfragen

1. Können Sie sich ein Anwendungsszenario vorstellen, in der  das spezifische Verhalten von SelectionSort (im Hinblick auf  die Ergebnisentstehung) besser ist, als das von InsertionSort? 

2. Welches Sortierverfahren würden Sie wählen, wenn Sie mit 10 

HIWIs eine Klausur von 400 Studenten kontrollieren und diese 

am Ende nach der Matrikelnummer sortiert stapeln müssten?

(38)

Vertiefung in

“Algorithmen und Datenstrukturen”

Weitere Verfahren (z.B. QuickSort, HeapSort) Nichttriviale Implementationen

Nicht-vergleichsbasierte Verfahren

Genauere Herleitung von Komplexitäten

...

(39)

Zusammenfassung

Sortieren ist ein fundamentales Problem.

Viele Wege führen nach Rom.

Ausblick

Welcher Weg ist effizient(er)?

Wie weiß man, dass korrekt sortiert wird?

Wie abstrahiert man z.B. von dem Elementtyp?

...

Referenzen

ÄHNLICHE DOKUMENTE

mit Wurzel ≥ i erf¨ ullen die Heapeigenschaft Nach Aufruf von Build-Heap (A) enth¨ alt A dieselben Eintr¨ age wie zuvor, aber nunmehr bildet A einen heap der Gr¨ oße n....

• Die Idee des Sortierens durch Mischen könnte auch mithilfe von Feldern realisiert werden (wie ?-). • Sowohl das Mischen wie das Sortieren könnte man statt rekursiv auch

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

Schreibe die Wörter mit Gross- und Kleinbuchstaben in die richtige Spalte. Schreibe die Wörter mit Gross- und Kleinbuchstaben in die

In der Praxis werden h¨ aufig Kombinationen mehrerer Verfahren verwendet. ▸

• Bucketsort beginnend mit dem letzten Zeichen so oft aufrufen, wie das längste Wort lang ist. • Beobachtung: Bucketsort ist stabiles

D1.3 Sortieren von Strings D1.4 LSD-Sortierverfahren D1.5 Quicksort.. L¨ uthi (Universit¨ at Basel) Algorithmen und

Informell: Wenn ein “comparison-swap Algorithmus” Booleans korrekt sortiert, dann auch ganze Zahlen.. Formal: