1 Datastructuren Quicksort College 3. 2 Vorige keren O-notaties Sorteren: insertion sort, bubble...
-
Upload
cecilia-visser -
Category
Documents
-
view
219 -
download
0
Transcript of 1 Datastructuren Quicksort College 3. 2 Vorige keren O-notaties Sorteren: insertion sort, bubble...
1
Datastructuren
Quicksort
College 3
2
Vorige keren
O-notaties Sorteren: insertion sort, bubble sort
Kosten (n2) tijd in het slechtste geval
Sorteren: merge sort Kosten (n lg n) tijd in het slechtste geval
Zoeken: binary search Zoeken in een geordende array: (lg n) tijd
Quicksort: begin
3
Vandaag
O-notatie: en Quicksort: eind Heapsort
4
Sorteeralgoritmenoverzicht
(n2): bubble sort, insertion sort (n lg n): merge sort, heapsort (komt nog) Geen extra geheugen: bubble sort, insertion
sort, heapsort Wel extra geheugen: merge sort
5
1
Orde notaties
6
O-notatie en zo
O-notatie (herhaling): O(g(n)) = { f(n) | er zijn positieve constanten c en r, zodat 0
f(n) c * g(n) voor alle n r} O(g(n)) is dus een verzameling functies. In plaats van de
schrijven f(n) O(g(n)) schrijft men echter f(n)=O(g(n)) Allemaal waar:
3n2 = O(n2) (7 n lg n3) = O(n lg n) (2n3+4n2 +3n + 5) = O(n3)
Maar ook zijn waar: n lg n = O(n2) n3 = O(n4) Want “O” geeft een bovengrens
7
Bewijzen dat algoritme O-grens haalt
Te bewijzen: algoritme gebruikt O(f(n)) tijd. Zo doe je dat:
Toon aan dat voor alle inputs, de tijd niet meer is dan een constante maal f(n), n de inputgrootte
Verschillende methoden: Inspectie van loop-structuur Analyse van “recursieboom” Andere technieken komen nog
8
Voorbeeld
z = 0; for i = 1 to n do
for j = 1 to n * n do• k = 1• while k < n * n do• z = z + i * j * k• k = k*2
• z ++;z = z + 3;
return z
9
-notatie (Omega)
-notatie: (g(n)) = { f(n) | er zijn positieve constanten c en r,
zodat f(n) c * g(n) voor alle n r} (g(n)) is dus weer een verzameling functies. In plaats
van de schrijven f(n) (g(n)) schrijft men echter f(n)= (g(n))
Deze notatie geeft ondergrenzen, terwijl de O-notatie bovengrenzen gaf
Vb.: het bubblesort-algoritme gebruikt in het slechtste geval n2) tijd
Vb.: het mergesort-algoritme gebruikt in het slechtste geval (n lg n) tijd
10
Voorbeelden
Allemaal waar: 3n2 = (n2) (7 n lg n3) = (n lg n) (2n3+4n2 +3n + 5) = (n3)
Maar ook zijn waar: n lg n = (n) n3 = (n2) Want “” geeft een ondergrens
11
-notatie (Theta)
-notatie combineert O-notatie en -notatie f(n) = (g(n)), dan en slechts dan als
f(n) = O(g(n)) en f(n) = (g(n)) Dus:
3n2 = (n2) Maar niet: 3n2 = (n3) en niet: 3n3 = (n2)
12
Van snel naar langzaam
(1), (lg lg n) (lg n), (lg2 n), (n), (n), (n lg n), (n lg2 n), (n n), (n2), (n2 lg n), (n3), (n4), (2n), (3n), (n!), (busybeaver(n)) (bijvoorbeeld: maximum aantal
stappen dat een terminerend programma met n symbolen opgeschreven kan doen)
Snel algoritme langzaam stijgende functie (en omgekeerd)
13
Herhaling + Vandaag
Quicksort Snel sorteer algoritme Gebruikt gemiddeld weinig tijd: (n lg n) met in
de praktijk een kleine constante Maakt gebruik van belangrijke subroutine:
Partition Quicksort is langzaam in het slechtste geval, maar
snel op random inputs Randomized-Quicksort om slechte gevallen
‘meestal’ te vermijden Wiskundige analyse van gemiddelde tijd
Randomized-Quicksort
14
Quicksort
Verdeel en heers paradigma Idee is:
Kies een element uit de array, zeg x Splits de array in drie stukken:
• Alles in 1e stuk is x• 2e stuk is het element x• Alles in 3e stuk is x (of >)
Sorteer recursief het eerste stuk Sorteer recursief het derde stuk Klaar!
15
PARTITIONQuicksort: Eén
Datastructuren
16
Splitsen
Partition(A,p,r) {Input is array A met
indexwaardes van p tot en met r}
{Output: waarde q met p q r zodat A[p..r] een permutatie is van input, en als p i q dan geldt A[i] A[q] en als q i r dan geldt A[i] A[q]}
…
Methode partitioneert array A[p…r]
Returnwaarde is plek waar “splitselement” terechtgekomen is
Splitselement heet pivot en nemen we nu als element dat op A[r] staat
17
Partition
Code in boek is subtielpivot
Allemaal Allemaal
Gebied waar we nogaan werken
i j-1p ri+1 j
18
Pseudocode Partition
Partition(A,p,r) pivot = A[r]; i = p – 1; for j = p to r – 1 do
{*} if A[j] pivot then
• i ++;• Verwissel A[i] en A[j]
Verwissel A[i+1] en A[r];
return i+1;
Invariant: bij * geldt voor elke k, p k r:1. Als p k i, dan A[k]
pivot2. Als i+1 k j – 1,
dan A[k] pivot3. Als k=r, dan
A[k]=pivot
19
Pseudocode Partition
Partition(A,p,r) pivot = A[r]; i = p – 1; for j = p to r – 1 do
{*} if A[j] pivot then
• i ++;• Verwissel A[i] en A[j]
Verwissel A[i+1] en A[r];
return i+1;
Invariant: bij * geldt voor elke k, p k r:1. Als p k i, dan A[k]
pivot2. Als i+1 k j – 1,
dan A[k] pivot3. Als k=r, dan
A[k]=pivot Merk op:
Initieel geldt invariant: triviaal
Invariant blijft gelden Bij terminatie …
20
Partition na de loop
En dan verwisselen we A[i+1] en A[r]
Allemaal Allemaal
ip ri+1
Allemaal Allemaal
i+1p r
21
Looptijd partition
Partition(A,p,r) pivot = A[r]; i = p – 1; for j = p to r – 1 do
{*} if A[j] pivot then
• i ++;• Verwissel A[i] en A[j]
Verwissel A[i+1] en A[r];
return i+1;
Lineair(r-p+1) Inspectie van
loopstructuur
22
Opmerking (herhaling)
In onze beschrijving gingen we er van uit dat alle elementen verschillend zijn
Als er gelijke elementen zijn, werkt het ook, maar moet je iets beter opletten in de analyse (zelfde code kan gebruikt worden)
Datastructuren
23
CODE EN EERSTE ANALYSE
Quicksort: Twee
Datastructuren
24
Quicksort
Quicksort(A, p, r) {Sorteert het deel van de array A[p…r]} if p < r then
q = Partition(A, p, r)Quicksort(A, p, q-1)Quicksort(A, q+1, r)
25
Allemaal Allemaal
q
r
rp
p
26
Hoeveel tijd kost Quicksort?
In het slechtste geval gaat het erg langzaam…
Bekijk een gesorteerde rij: We splitsen in stukken van grootte n – 1; 1; 0 En de volgende keer in stukken van grootte n-2;
1; 0 Etc. Dus: cn+ c(n-1)+ c(n-2)+ c(n-3) + … +3c+2c+c
= c n(n+1)/2 stappen Op een gesorteerde rij: (n2) stappen
27
Analyse met recurrente betrekkingen
Schrijf: T(n) is aantal stappen van Quicksort op gesorteerd array met n elementen
T(n) = T(n-1)+T(0) + (n)= T(n-1)+ (n)= (n2)
Andere constantes
Met inductie naar n
28
Quicksort voor aartsoptimisten
Als we echt geluk hebben, splitst Quicksort altijd precies middendoor en gaan we in recursie op twee stukken van hooguit n/2 elementen
Zelfde analyse als bij Mergesort geeft(n lg n) tijd
29
log n niveau’slog n niveau’s
30
Beste geval analyse van Quicksort met recurrente betrekkingen
Stel T(n) is het beste geval van de looptijd van Quicksort op een array met n elementen
T(n) 2*T(n /2) + O(n) (*) T(n) = O(n lg n)
Volgt uit (*) met inductie
Zo kan je ook Mergesort analyseren
31
Quicksort voor optimisten (niet noodzakelijk aartsoptimisten)
Stel nu dat we altijd verdelingen hebben die de array splitsen in twee stukken die verhouding 9 – 1 hebben
T(n) = T(9n / 10)+ T(n / 10) + (n) Recursieboom heeft log10/9 n = (lg n) lagen Per laag (n) dus in zo’n geval eveneens
(n lg n) Maar … hoe vaak gebeurt dat?
32
Hoe vaak doen we een goede splitsing?
In 80% van de gevallen splitsen we 9-1 of beter…
Ingewikkelde analyse geeft (n lg n) tijd gemiddeld over alle mogelijke permutaties van input als alle getallen verschillend zijn (doen we niet)
33
RANDOMIZED QUICKSORTDrie
Datastructuren
34
Hoe zorgen we ervoor dat we heel vaak goed splitsen
Idee 1: maak eerst een random permutatie van de input Geeft (n lg n) Analyse ingewikkeld
Idee 2 (beter): gebruik niet A[r] als pivot, maar gebruik een random element als pivot Geeft ook (n lg n) Analyse eenvoudiger Ietsje sneller
35
Randomized-Partition
Randomized-Partition(A,p,r) Kies uniform een random getal i uit de
verzameling {p, p+1, …, r} Verwissel A[r] en A[i] Partition(A,p,r)
Elk element in A heeft dezelfde kansom als pivot-element gebruikt te worden
Elk element in A heeft dezelfde kansom als pivot-element gebruikt te worden
36
Allemaal Allemaal
q
r
rp
p
37
Quicksort
Quicksort(A, p, r) {Sorteert het deel van de array A[p…r]} if p < r then
q = Partition(A, p, r)Quicksort(A, p, q-1)Quicksort(A, q+1, r)
38
Randomized-Quicksort pseudocode
Randomized-Quicksort(A, p, r) {Sorteert het deel van de array A[p…r]} if p < r then
q = Randomized-Partition(A,p,r)Randomized-Quicksort(A, p, q-1)Randomized-Quicksort(A, q+1, r)
39
Analyse Randomized Quicksort
Verschillende manieren om de verwachtte tijd uit te rekenen
Netjes: stel recurrente betrekking op, en los die op (zie o.a. sheets)
Vandaag: telargument waarbij we kijken naar “hoe vaak doet een element mee in een partition”?
40
Tijd is O(som partition-lengtes)
Kijk naar recursieboom Totale tijd is O(som van alle lengtes van alle
deelstukken waar we een partitie op doen) = O(som over alle elementen van aantal keren
dat het element in een partitie mee doet)
41
Verwachtte tijd
Totale verwachtte tijd is O(verwachte som van alle lengtes van alle deelstukken waar we een partitie op doen)
= O(som over alle elementen van verwachtte
aantal keren dat het element in een partitie mee doet)
= n* O(verwachtte aantal keren dat een element in een partitie meedoet)
42
Afschatten van verwachtte aantal keren dat een element in een partitie meedoet
Is O(log n) Hoe laten we dit zien? Kijk element x, en kijk naar het formaat van
het stuk waar x in zit. Begint met formaat n Iedere keer een beetje kleiner Als formaat 1 is zijn we klaar Hoe vaak is het verwachtte aantal keren dat
het kleiner wordt? We laten zien: O(log n)
43
Kans is ½ dat stuk hooguit ¾ van oude lengte heeft
Als we een stuk hebben met r elementen zijn er r/2 keuzes voor de pivot die zorgen dat de volgende keer het grootste stuk hooguit ¾ * r lang is
44
Tellerij klaar
Hoe vaak kan je n met ¾ vermenigvuldigen totdat je onder de 1 bent? log4/3 n keer = O(log n)
Wat is het verwachtte aantal keren dat je een experiment met kans ½ moet doen totdat je s keer succes hebt? 2s
Dus verwachtte aantal keren dat element in partitie meedoet is hooguit 2 log4/3 n = O(log n) keer
Dus: verwachtte tijd Quicksort O(n log n) Andere analyse (wel in sheets, niet vandaag):
2n ln n
45
Analyse Randomized-Partition
Slechtste geval: weer (n2) T(n) = max0 q n-1 T(q)+T(n-q-1)+(n)
Verwachtte tijd: analyse doen we hier aannemend dat alle elementen verschillend zijn (anders klopt ‘t ook, overigens)
We doen de analyse hier met behulp van de sommatiefactormethode
Eerst: vergelijking looptijd en aantal vergelijkingen
Deze sheet slaan we over
Deze sheet slaan we over
46
Looptijd vs aantal vergelijkingen
Stel Quicksort doet X vergelijkingen. Dan gebruikt het O(n+X) tijd Partition doet altijd minstens 1 vergelijking
• Want we roepen Partition alleen aan op stukken met minstens 2 elementen
Partition doet O(aantal vergelijkingen in partition) werk …
We gaan nu het verwachtte aantal vergelijkingen tellen dat Quicksort doet op een array met n verschillende elementen. Noem dit getal C(n)
Deze sheet slaan we over
Deze sheet slaan we over
47
Technisch detail
We volgen de analyse uit Concrete Mathematics. Die gebruikt twee vergelijkingen per recursieve aanroep extra.
Deze waardes noemen we D(n). D(0)=C(0)=0; als n>0 dan is D(n)>C(n) Als we dus voor D(n) een bovengrens
hebben, geeft dat ook een bovengrens voor C(n) Uiteindelijke waarde is dus iets beter (scheelt niet
veel)
Deze sheet slaan we over
Deze sheet slaan we over
48
Aantal vergelijkingen (Randomized)-Partition
Partition(A,p,r) pivot = A[r]; i = p – 1; for j = p to r – 1 do
{*} if A[j] pivot then
• i ++;• Verwissel A[i] en A[j]
Verwissel A[i+1] en A[r];
return i+1;
n-1 vergelijkingen op een array met n elementen
Concrete Mathematics neemt hier n+1 vergelijkingen
Deze sheet slaan we over
Deze sheet slaan we over
49
Analyse D(n) (1)
D(0) = 0 D(1) = 2 D(n) = n+1 + ????
Elk van de splitsingen heeft dezelfde kans:• 0,1,n-1• 1,1,n-2• 2,1,n-3• …• n-2, 1, 1• n-1, 1, 0
Deze sheet slaan we over
Deze sheet slaan we over
50
Analyse D(n) (2)
D(0)= 0 D(1)= 2 D(n) = n+1 + 1/n*k=0
n-1 D(k) + 1/n*k=0n-1 D(n-k-1)
Elk van de splitsingen heeft dezelfde kans:• 0,1,n-1• 1,1,n-2• 2,1,n-3• …• n-2, 1, 1• n-1, 1, 0
Of: D(n) = n+1 + (2/n)*k=0n-1 D(k) voor n>0
Deze sheet slaan we over
Deze sheet slaan we over
51
1
0
)(2
1)(n
k
kDn
nnD
1
0
2 )(2)(n
k
kDnnnnD
2
0
2 )(211)1()1(n
k
kDnnnDn
)1(22)1()1()( nDnnDnnnD
-
nnDnnnD 2)1()1()(
Deze hadden we
Maal n nemen
Zelfde vergl. voor n-1
Vergelijkingen aftrekken
Na vereenvoudigen
Deze sheet slaan we over
Deze sheet slaan we over
52
Stelsel vergelijkingen
D(0)=0 nD(n) = (n+1)D(n-1)+ 2n
Dit stelsel kunnen we met sommatiefactormethode oplossen
Idee is: vermenigvuldig formule met sommatiefactor sn waarbij
• sn = (an-1an-2…a1)/(bnbn-1…b2) als anD(n)=bnD(n-1)+cn
• Want dan is snbn=sn-1an-1
• En dan krijg je voor E(n)=snanD(n) de formuleE(n)=E(n-1)+sncn
• Wat een somformule voor E en daarna voor D geeft…
Deze sheet slaan we over
Deze sheet slaan we over
53
nnnn
nnsn )1(
2
3)1(
1)2()1(
D(0)=0nD(n) = (n+1)D(n-1)+ 2nan = nbn = n+1cn = 2n
nnn
nDnnn
nnDnn
2)1(
2)1()1(
)1(
2)(
)1(
2
1
)(2)(
)1(
2)()(
n
nDnDn
nnnDasnE nn
1
4)1()(
nnEnE
: dit hadden we
Definitie toepassen:
Allesmaal sn:
Def.:
(*) en (**)geven:
(*)
(**)
Deze sheet slaan we over
Deze sheet slaan we over
54
1
4)1()(
nnEnE
n
k knE
1 1
4)(
1
)(2)(
n
nDnE
dus
We hadden
dus
n
k knnD
1 1
1)1(2)(
Want E(0)=0
Deze sheet slaan we over
Deze sheet slaan we over
55
Aantal vergelijkingen randomized quicksort
n
kn n
kH
1
ln1
n
k knnD
1 1
1)1(2)(
Randomized-Quicksort doet verwachtongeveer 2(n+1)ln n vergelijkingen
Deze sheet slaan we over
Deze sheet slaan we over
56
Resultaat en discussie
Het verwachtte aantal vergelijkingen van Randomized-Quicksort is minder dan 2(n+1)ln n
Verwachtte looptijd is (n lg n) De in de O / verstopte constante is erg
klein, dus heel snel in de praktijk Sommige hele snelle sorteermethoden
switchen naar een ander algoritme wanneer n klein is (bijvoorbeeld onder de 30)
57
Recap
Quicksort Snel sorteer algoritme Gebruikt gemiddeld weinig tijd: (n lg n) met in
de praktijk een kleine constante Maakt gebruik van belangrijke subroutine:
Partition Quicksort is langzaam in het slechtste geval, maar
snel op random inputs Randomized-Quicksort om slechte gevallen
‘meestal’ te vermijden Wiskundige analyse van gemiddelde tijd
Randomized-Quicksort
58
Sorteeralgoritmenoverzicht
Slechtste en gemiddeld geval (n2): bubble sort, insertion sort
Slechtste en gemiddeld geval (n lg n): merge sort, heapsort (zometeen)
Slechtste geval (n2) en gemiddeld geval (n lg n): quicksort Voordeel van Quicksort vooral in de “” verstopt
Geen extra geheugen: bubble sort, insertion sort, heapsort, quicksort
Wel extra geheugen: merge sort