TDDD73 Funktionell och imperativ programmering i Python Föreläsning 13
Algoritmer
Peter Dalenius
Institutionen för datavetenskap
Inför kursavslutning
• Deadline för laborationer är sista dagen i läsperioden, d.v.s.
fredag 20 december 2013.
• Datortentan är tisdag 14 januari 2014, antingen 8-13 eller 14-19.
• Anmälan till tentan sker 15/12 - 4/1 via Studentportalen. Om man inte är anmäld finns det en mycket stor risk att man inte får skriva tentan.
• Nästa föreläsning kommer att bestå av två delar: en kort
repetition av några av de viktigaste delarna av kursen samt en genomgång av en exempeltenta.
Översikt
• Två sätt att göra selection sort
• Två sätt att göra insertion sort
• Rekursiva algoritmer
• Tornet i Hanoi
• Introduktion till quick sort
Selection sort (informell beskrivning)
Antag att vi har en hög med kort som vardera har ett heltal på framsidan. Högen är blandad och vår uppgift är att sortera dem i stigande ordning. Detta kan vi göra så här:
• Gå igenom högen och hitta kortet med det minsta talet.
• Flytta detta kort till början av högen.
• Upprepa proceduren med resten av högen, till dess att vi gått igenom alla kort.
Selection sort (illustration)
0
14
1
11
2
15
3
13
4
12
sorterad ej sorterad
botten minsta
Selection sort (illustration)
0
11
1
14
2
15
3
13
4
12
sorterad ej sorterad
botten minsta
Selection sort (illustration)
0
11
1
12
2
15
3
13
4
14
sorterad ej sorterad
botten minsta
Selection sort (illustration)
0
11
1
12
2
13
3
15
4
14
sorterad ej sorterad
botten minsta
Selection sort (illustration)
0
11
1
12
2
13
3
14
4
15
sorterad ej sorterad
Selection sort (implementation)
def selectionsort_inplace(seq):
n = len(seq)
for bottom in range(n-1):
mp = bottom
for i in range(bottom+1, n):
if seq[i] < seq[mp]:
mp = i
seq[bottom], seq[mp] = seq[mp], seq[bottom]
Selection sort (illustration)
0
14
1
11
2
15
3
13
4
12
11
sorterad ej sorterad
minsta
Kopierande version
Selection sort (illustration)
0
14
1
15
2
13
3
12
0
11
sorterad ej sorterad
minsta
1
12
Kopierande version
Selection sort (illustration)
0
14
1
15
2
13
11
sorterad ej sorterad
minsta
12 13
Kopierande version
Selection sort (illustration)
0
14
1
15
0
11
sorterad ej sorterad
minsta
1
12
2
13
3
14
Kopierande version
Selection sort (illustration)
0
15
11
sorterad ej sorterad
minsta
12 13 14 15
Kopierande version
Selection sort (implementation)
def selectionsort_copy(seq):
res = []
while seq:
e = min(seq) res.append(e) seq.remove(e) return res
Kopierande version
Insertion sort (informell beskrivning)
Antag att vi har en hög med kort som vardera har ett heltal på framsidan. Högen är blandad och vår uppgift är att sortera dem i stigande ordning. Detta kan vi göra så här:
• Dela upp högen i två delar: en del som innehåller det första kortet (som vi anser är en sorterad hög) och en del som innehåller resten.
• Ta det översta kortet i resten och sortera in det på rätt plats i den sorterade högen.
• Upprepa proceduren till dess att vi gått igenom alla kort.
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
11
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
hål
11
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
hål
11
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
11
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
11
hål
Insertion sort (illustration)
0
14
1 2
15
3
13
4
12
sorterad ej sorterad
11
Och så vidare…
Insertion sort (implementation)
def insertionsort_inplace(seq):
for i in range(1, len(seq)):
item = seq[i]
hole = i
while hole > 0 and seq[hole-1] > item:
seq[hole]= seq[hole-1]
hole -= 1 seq[hole] = item
Insertion sort (illustration)
0
14
1
11
2
15
3
13
4
12
14
sorterad ej sorterad
Kopierande version
Insertion sort (illustration)
0
14
1
11
2
15
3
13
4
12
0
14
sorterad ej sorterad
Kopierande version
Insertion sort (illustration)
0
14
1
11
2
15
3
13
4
12
11
sorterad ej sorterad
14 15
Och så vidare…Kopierande version
Insertion sort (implementation)
def insertionsort_copy(seq):
res = []
for e in seq:
i = 0
while True:
if i >= len(res) or res[i] > e:
break i += 1
res.insert(i, e)
return res Kopierande version
Rekursiva algoritmer
• En del problem lämpar sig särskilt bra att lösa rekursivt. Givet ett problem försöker man först lösa ett mindre problem
(rekursivt) för att sedan utöka denna lösning till att gälla hela problemet. Denna metod kan ge upphov till mycket effektiva algoritmer.
• Som första illustrerande exempel ska vi skapa en funktion anagrams som givet en sträng producerar en lista med alla anagram, dvs alla strängar som innehåller samma bokstäver i alla möjliga ordningar.
Induktiv metod
'abc'
1. Utgå från ett exempel
['abc', 'bac', 'bca', 'acb', 'cab', 'cba']
anagrams()
2. Bestäm vad hela resultatet ska bli
'a' + 'bc' 3. Dela upp i första och resten
['bc', 'cb']
anagrams()
4. Bestäm vad resultatet av resten ska bli
5. Bestäm operation som givet första och resultat av resten ger hela resultetat
Peta in ’a’ på alla möjliga ställen i alla delanagram
Anagramproblemets lösning
def anagrams(s):
if s == "":
return [s]
else:
ans = []
for w in anagrams(s[1:]):
for pos in range(len(w)+1):
ans.append(w[:pos]+s[0]+w[pos:]) return ans
Tornet i Hanoi
Tornet i Hanoi
Regler för förflyttning:
• Endast en skiva i taget får flyttas.
• Skivorna får inte läggas åt sidan utan måste placeras på en av de tre stolparna.
• En större skiva får aldrig placeras ovanpå en mindre skiva.
Tornet i Hanoi
Flytta ett torn med 1 skiva från A till C:
• Flytta skivan från A till C.
Flytta ett torn med 2 skivor från A till C med B som mellanlagring:
• Flytta en skiva från A till B.
• Flytta en skiva från A till C.
• Flytta en skiva från B till C.
Flytta ett torn med 3 skivor från A till C med B som mellanlagring:
• Flytta ett torn med 2 skivor från A till B med C som mellanlagring.
• Flytta en skiva från A till C.
Tornet i Hanoi
Flytta ett torn med n skivor från x till z med y som mellanlagring:
• Om n = 1
• Flytta en skiva från x till z.
• Om n > 1
• Flytta ett torn med n-1 skivor från x till y med z som mellanlagring.
• Flytta ett torn med 1 skiva från x till z med y som mellanlagring.
• Flytta ett torn med n-1 skivor från z till y med x som mellanlagring.
def move_tower(n, source, dest, temp):
if n == 1:
print("Move disk from", source, "to", dest+".") else:
Något om komplexitet
• Algoritmen är mycket kort, men varje steg ger upphov till två rekursiva anrop med n - 1.
• Detta innebär att ett problem med n diskar kommer att kräva 2n - 1 antal steg, dvs problemet löses i exponentiell tid.
• Ett problem med 64 skivor kräver inte mindre än
18446744073709551615 steg.
Antal skivor Antal lösningssteg
1 1
2 3
3 7
4 15
5 31
6 63
7 127
8 255
9 511
10 1023
Quick sort (informell beskrivning)
Antag att vi har en hög med kort som vardera har ett heltal på framsidan. Högen är blandad och vår uppgift är att sortera dem i stigande ordning. Detta kan vi göra så här:
• Välj ut ett kort som vi kallar pivotelement.
• Dela upp resten av högen i två delar: en som innehåller alla kort som är mindre än pivotelementet och en som innehåller alla som är större än eller lika med pivotelementet.
• Sortera varje hög för sig genom att köra algoritmen från början.
• Lägg ihop de sorterade högarna i rätt ordning med
Quick sort (illustration)
15 11 16 13 18 14 17 12
11 13 14 12 16 18 17
15
11 12 13 14 16 17 18
11 12 13 14 15 16 17 18
1. Välj pivotelement
2. Partitionera (dela upp)
3. Sortera delarna 3. Sortera delarna
4. Slå ihop delresultaten
Bildkällor:
http://commons.wikimedia.org/wiki/File:Tower_of_Hanoi.jpeg