Sortieren und Suchen mit Listen in Python IFB Speyer Daniel Jonietz Überblick Teil 1: Teil 2: Teil 3: Elementare Sortieralgorithmen Quicksort Effizienz von Sortierverfahren Teil 4: Suchalgorithmen
Download ReportTranscript Sortieren und Suchen mit Listen in Python IFB Speyer Daniel Jonietz Überblick Teil 1: Teil 2: Teil 3: Elementare Sortieralgorithmen Quicksort Effizienz von Sortierverfahren Teil 4: Suchalgorithmen
Sortieren und Suchen
mit Listen in Python
IFB Speyer Daniel Jonietz 2009
2
Überblick
Teil 1: Teil 2: Teil 3: Elementare Sortieralgorithmen Quicksort Effizienz von Sortierverfahren Teil 4: Suchalgorithmen
3
Teil 1
Elementare Sortieralgorithmen
4
Motivation
Eine Reihe von Werten liegt unsortiert vor.
Ziel: Die Werte sollen (aufsteigend) sortiert werden.
5
Datenmodell
Die Werte liegen in einer Liste vor:
Index 0 1 2
...
...
len(L)-1 len(L) Wert
6
Liste mit zufälligen Zahlen füllen
def datenErzeugen(anzahl): L = [] for i in range(anzahl): L = L + [randint(1, 10000)] return L daten = datenErzeugen(100) print daten
Sortieren durch Auswahl
7
Idee: Suche das kleinste Element und lege es beiseite. Dann wähle aus den übrigen wiederum das kleinste Element und lege es daneben.
Sortieren von Münzen
8
1 1 1 1 1 1 1
Auswahl-Sortieren V1
5 2 2 2 2 2 2 3 3 3 3 3 4 4 4 4 5 5 5 7 7 8 5 5 5 5 7 7 7 7 7 7 2 2 8 8 8 8 8 8 8 3 3 3 1 4 4 4 4
9
Auswahl-Sortieren V2
„in situ“ 5 1 1 1 1 1 1 1 7 7 2 2 2 2 2 2 2 2 7 3 3 3 3 3 8 8 8 8 4 4 4 4 3 3 3 7 7 5 5 5 1 5 5 5 5 7 7 7 4 4 4 4 8 8 8 8
Algorithmus
10 minsort
Für i von 0 bis Anzahl-1 Suche das Minimum aus den restlichen Elementen Tausche das Minimum mit dem Wert an der Position i Brauchen Möglichkeit zur Bestimmung des Minimums aus einem Bereich der Zahlen
11
Minimum und Maximum
12
Aufgabe
Implementieren Sie die Funktionen
min(liste) max(liste)
die den Index eines minimalen Elementes aus der Liste liefern.
bzw. maximalen Implementieren Sie damit
minSort(liste)
Wer möchte, auch
maxSort(liste)
. Idee?
Lösungsvorschlag
13 def min(liste): kandidat = 0 for i in range(len(liste)): if (liste[i] < liste[kandidat]): kandidat = i return kandidat def max(liste): kandidat = 0 for i in range(len(liste)): if (liste[i] > liste[kandidat]): kandidat = i return kandidat
Lösungsvorschlag
def minSort(liste): for i in range(len(liste)): m = min(liste[i:len(liste)]) (liste[m+i], liste[i]) = (liste[i], liste[m+i]) 14 def maxSort(liste): for i in range(len(liste)-1,0,-1): m = max(liste[0:i+1]) (liste[m], liste[i]) = (liste[i], liste[m])
Idee: suche immer das Maximum und sammle von rechts
15
Sortieren durch Einfügen
Idee: Nimm das nächste Element und füge es sortiert ein.
Sortieren eines Kartenspiels
16
Sortieren durch Einfügen
5 7 2 7 5 5 2 2 2 1 1 2 2 7 5 5 3 7 7 5 3 3 8 7 5 4 8 7 5 8 7 8 2 2 8 8 8 8 3 3 3 3 3 1 1 1 1 1 1 4 4 4 4 4 4 4
17
Sortieren durch Einfügen
5 7 2 8 3 „in situ“ 7 7 5 5 3 2 2 5 5 2 2 2 1 1 2 2 7 7 5 3 3 3 3 3 3 8 7 5 8 8 8 8 7 5 4 4 4 4 4 4 4 4 8 1 1 1 1 1 1 8 7
18
Aufgabe
Implementieren Sie
insertionSort(liste)
19
Lösungsvorschlag
def insertionSort(liste): sortiert = [] for i in range(len(liste)): element = liste[i] j = 0 for k in range(len(sortiert)): if (sortiert[k] < element): j = k+1 sortiert = sortiert[:j]+[element]+sortiert[j:] return sortiert
Bubblesort
20
Idee: Vergleiche paarweise und schiebe große Elemente nach hinten Sortieren wie Blasen in einem Wasserglas aufsteigen: Große Blasen steigen schnell auf
21
Bubblesort - Beispiel
5 7 2 1 1 5 2 2 2 2 2 2 5 3 1 3 3 7 3 1 3 8 3 1 4 4 4 4 3 1 4 5 5 5 5 1 4 7 7 7 7 7 4 8 8 8 8 8 8
Algorithmus
bubblesort
Für i von 0 bis Anzahl-1 Element i > Element i+1 ?
ja Vertausche beide Wiederhole bis keine Vertauschung stattfand nein
22
Ende des Sortiervorgangs: – – Wenn keine Vertauschung mehr stattfand spätestens nach „Anzahl“ Schleifendurchläufen
23
Aufgaben
Implementieren Sie
bubbleSort(liste);
Der vorgestellte Bubblesort-Algorithmus kann noch verbessert werden: Die innere Schleife muss nicht immer bis zum Ende durchlaufen werden. Durchdenken Sie dies und verbessern Sie Ihre Implementierung.
24
Lösungsvorschlag
def bubbleSort(liste): getauscht = True while (getauscht == True): getauscht = False for i in range(len(liste)-1): if (liste[i] > liste[i+1]): (liste[i], liste[i+1]) = (liste[i+1], liste[i]) getauscht = True;
25
Teil 2
Quicksort
Quicksort
26
Prinzip: Teile und Herrsche Wähle ein Pivot-Element, das das Problem in zwei Teilprobleme zerlegt.
Ein Bereich enthält dann alle Elemente, die kleiner sind als das Pivot-Element, der andere Bereich alle Elemente, die größer sind. Löse die Teilprobleme auf die gleiche Art und Weise.
27
Quicksort - Beispiel
5 1 8 4 3 7 2 2 1 3 4 8 7 5 1 2 3 4 5 7 8 1 2 3 4 5 7 8 1 2 3 4 5 7 8
Quicksort - Pivot-Element
28
Die Wahl des Pivot-Elementes beeinflusst wesentlich die Anzahl benötigter Durchgänge schlecht:
p = min()
und
p = max()
gut:
p = Zahlen[(links + rechts) // 2]
gut: Feld mittleren Wertes optimal: ein Element das den zu sortierenden Bereich in zwei gleich große Teile partitioniert
29
Aufgaben
Schreiben Sie die Funktion
pivot (liste)
Implementieren Sie
zerlege (liste, pivot)
so, dass
zerlege
drei Teillisten zurückliefert und damit dann insgesamt Quicksort
quicksort(liste)
30
Lösungsvorschlag
def pivot(liste): return liste[len(liste) // 2]
Lösungsvorschlag
31 def zerlege(liste, pivot): kleinerPivot = [] gleichPivot = [] groesserPivot = [] for i in range(len(liste)): if (liste[i] < pivot): kleinerPivot = kleinerPivot + [liste[i]] elif (liste[i] > pivot): groesserPivot = groesserPivot + [liste[i]] else: gleichPivot = gleichPivot + [liste[i]] return [kleinerPivot, gleichPivot, groesserPivot]
Lösungsvorschlag
32 def quicksort(liste): teilListen = zerlege(liste, pivot(liste)) ergebnis = [] if (teilListen[0]!=[]): ergebnis = ergebnis + quicksort(teilListen[0]) ergebnis = ergebnis + teilListen[1] if (teilListen[2])!=[]): ergebnis = ergebnis + quicksort(teilListen[2]) return ergebnis
33
Weitere Sortierverfahren
Heapsort Shellsort Bucketsort Platzziffersortieren Mergesort
34
Teil 3
Effizienz von Sortierverfahren
Kriterien
35
Stabilität – Bleiben evtl. vorhandene Vorsortierungen erhalten?
Geschwindigkeit – – Anzahl Vergleiche Anzahl Tauschoperationen Einfluss von Parametern auf den Sortiervorgang – Quicksort: Bestimmung des Pivot-Elementes
36
Stabilität
Was passiert mit nach anderen Kriterien bereits sortierten Daten? Angenommen, Grün < Rot 1 4 3 4 1 4 2 1 1 2 3 4 4 4 Auswahl (von links) 1 1 2 3 4 4 4 Auswahl (von rechts)
37
Stabilität
Beispiel: Adressdaten (Telefonbuch o.ä.) Daten: – Name – Ort – ...
Sind bereits sortiert nach Ort , sollen jetzt nach Name sortiert werden Die Vorsortierung soll erhalten bleiben!
Komplexität
Unterscheiden 3 Fälle: – Best Case – – (Average Case) Worst Case
38
Aufwandsbestimmung – – – Messung Zählung und arithmetische Rechnung asymptotische Abschätzung
39
Aufwand - Zeit
Die Laufzeiten von Algorithmen lassen sich in python gut experimentell bestimmen:
import timeit t1 = timeit.Timer("insertionSort(daten)", "from __main__ import insertionSort, daten") print float(sum((t1.repeat(10, 1))))
40
Aufwand - Operationen
Operationen wie Vergleichen und Tauschen von Elementen aber auch das Erzeugen und Konkatenieren von Listen sind "teuer".
Der Aufwand lässt sich mit Zählern experimentell ermitteln
41
Experimente
Verwenden Zähler zur Abschätzung des Aufwandes
Aufgaben
42
Erweitern Sie die Algorithmen so, dass die entsprechenden Zähler erhöht werden.
–
min
bzw.
max
– –
minSort
bzw.
maxSort
,
bubbleSort, insertionSort zerlege
,
quicksort
Untersuchen Sie experimentell den Aufwand bei der Sortierung einiger Zahlenreihen. Wie verhalten sich die verschiedenen Verfahren bei bereits sortierten und umgekehrt sortierten Daten?
43
Theoretische Aufwandsbetrachtung
Welchen Aufwand hat ein Verfahren theoretisch maximal / minimal?
In der Informatik wird häufig das Verfahren der asymptotischen Aufwandsabschätzung vorgenommen
Groß-O-Notation
Wenn für die Laufzeit T(n) eines Algorithmus gilt: T(n) c n für eine Konstante c>0 und alle Werte n>n 0 , so sagt man „ T(n) ist in O(n) “
44
(I.d.R. reicht es den „stärksten“ Ausdruck zu wählen.)
Aufwand minsort
45
Aufwand für die Suche des Minimums: – beim 1. Durchlauf: – – beim 2. Durchlauf: beim n. Duchlauf: n-1 Vergleiche n-2 Vergleiche n-n Vergleiche – Gesamt: n (n - i) = 0.5
n² 0.5n in O(n²) i=1 Tauschoperationen: – in jedem Durchlauf genau eine, also gesamt n 1 Stück in O(n)
46
Aufwand bubbleSort
Vergleichsoperationen (best case) – beim 1. Durchlauf: – – Fertig!
O(n) n-1 Vergleiche Tauschoperationen (best case) – – keine O(1)
47
Aufwand bubbleSort
Vergleichsoperationen (worst case) – – beim 1. Durchlauf: beim 2. Durchlauf: n-1 Vergleiche n-1 Vergleiche – – – ...
beim n. Duchlauf:n-1 Vergleiche Gesamt: n (n 1) = n²-n in O(n²)
Aufwand bubbleSort
48
Tauschoperationen (worst case) – – beim 1. Durchlauf: beim 2. Durchlauf: n-1 Austausche n-2 Austausche – – ...
beim n. Durchlauf: n-n Austausche – Gesamt: n i=1 (n i) = 0.5n²-0.5n in O(n²)
49
Aufwand quicksort
Bestimmung des Pivot-Elementes – – hier so gestaltet, dass Aufwand zur Bestimmung vernachlässigbar aber: Wahl des Elementes hat großen Einfluß auf den weiteren Aufwand! Ungünstigste Wahl führt zu O(n²)!
50
Skizze zum Aufwand quicksort
Vereinfachte Analyse unter folgenden Bedingungen: – Anzahl Elemente 2er-Potenz: n=2 k – Zerlegung halbiert immer – – Zerlegung: fortwährende Halbierung führt zu Zerlegungstiefe log 2 (n) führt insgesamt auf: O(n log 2 (n))
Messergebnisse
51
Überblick und Ergebnisse der Zählungen n 10 100 1000 Minsort Bubblesort Quicksort 9 0 31 0 best 45 9 min/maxSort: 90 45 26 5 99 0 606 0 worst O(n²) best 4950 99 9900 4950 512 50 worst 999 0 9009 0 best 499500 999 999000 499500 8018 500 worst insertionSort: bubbleSort: quicksort: O(n²) O(n²) O(n log 2 (n)) Vergleiche Austausche Vergleiche Austausche Vergleiche Austausche
52
Teil 4
Suchalgorithmen
Suchalgorithmen
53
Zwei grundlegende Strategien: – – lineares (sequenzielles) Suchen binäres Suchen Beispiel Telefonbuch – Suche nach Namen: binär
(naja, in etwa)
– Suche nach Nummer: linear Beispiel Reihe von Zahlen – Suche nach Minimum und Maximum: linear
54
Lineares Suchen - Bsp
1 3 5 7 Suche nach Element 11 1 3 5 1 3 5 7 7 11 13 17 11 13 17 11 13 17 möglich unmöglich Testelement Treffer 1 1 1 3 3 3 5 5 5 7 11 13 17 7 11 13 17 7 11 13 17
55
Lineares Suchen
Prüfe der Reihe nach alle Elemente ab, bis das gesuchte Element gefunden ist oder keine Elemente mehr da sind.
keine Voraussetzungen an die Daten, dürfen auch unsortiert sein.
56
Lineares Suchen - Alg.
lineare_suche (wonach)
wert[pos]=wonach ja nein gefunden!
merke pos Gehe zur nächsten pos Wiederhole bis gefunden oder alles durchlaufen
Binäres Suchen
57
Voraussetzung: sortierte Daten Idee: – – – Beginne mit der Suche in der Mitte der Daten; wenn der Suchschlüssel kleiner ist suche in der Mitte des linken Bereiches weiter, wenn der Suchschlüssel größer ist suche in der Mitte des rechten Bereiches weiter.
58
Binäres Suchen - Beispiel
1 3 5 7 11 13 17 Suche nach Element 11 1 3 5 7 1 3 5 7 11 13 17 11 13 17 möglich unmöglich Testelement Treffer 1 3 5 7 11 13 17
59
Binäres Suchen - Alg.
binaeres_suchen (wonach)
links:= Anfang rechts:= Ende Berechne mittlere Position zwischen links und rechts wonach < wert(pos) ja ja rechts:= pos -1 wonach > wert(pos) links:= pos +1 Wiederhole bis gefunden oder links > rechts hier also: wonach = wert(pos) nein nein
60
Aufgabe
Vereinbarung: Wenn das Gesuchte nicht in den Daten enthalten ist soll
-1
zurückgegeben werden!
Implementieren Sie
lineareSuche(liste, wonach) binaereSuche(liste, wonach)
61
Lösungsvorschlag
def lineareSuche(liste, wonach): p = -1 for i in range(len(liste)): if (liste[i] == wonach): pos = i break return pos
62
Lösungsvorschlag
def binSuche(liste, wonach): links = 0 rechts = len(liste)-1 pos = 0 while (liste[pos] != wonach) and (links<=rechts): pos = (links + rechts) // 2 if (wonach < liste[pos]): rechts = pos -1 elif (wonach > liste[pos]): links = pos +1 if (wonach == liste[pos]): return pos else: return -1
Lineare vs. binäre Suche
63
Verdoppelt sich die Anzahl Elemente, so führt dies schlimmstenfalls zu – – einer Verdopplung des Aufwandes bei linearer Suche einem zusätzlichen Vergleich bei binärer Suche Einbau von Zählern kann dies verdeutlichen
64
Übung
Erweitern Sie die Suchfunktionen, indem Sie die Zähler für jeden benötigten Suchschritt (jeden benötigten Vergleich) erhöhen
binaere_suche(liste, wonach) lineare_suche(liste, wonach)
65
Such-Experimente
66
Weitere Suchverfahren
Fibonacci-Suche Sprungsuche