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 Report

Transcript 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