De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

1 Datastructuren Sorteren, zoeken en tijdsanalyse College 2.

Verwante presentaties


Presentatie over: "1 Datastructuren Sorteren, zoeken en tijdsanalyse College 2."— Transcript van de presentatie:

1 1 Datastructuren Sorteren, zoeken en tijdsanalyse College 2

2 2 Plan  O-notatie  Bewijzen met inductie  Sorteren: analyse van insertion sort  Bubble sort  Merge Sort  Quicksort  Heapsort (volgende keer)

3 3 Waarom O-notatie  Hoeveel operaties is nu eigenlijk een test als  if (A[i+1] > x) OR (x == 0)  ?  In elk geval: een constant aantal. Om dit niet precies te hoeven bekijken is de O-notatie bedacht: verstopt constanten in de notatie  8, 9, 20203, 1: allemaal O(1)  n, 4n, 10n + log(n), 21n: allemaal O(n) Datastructuren

4 4 “Asympthotic notation”  O: asympthotische bovengrens  Formeel:  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))  Intuïtie: we schrijven f(n) = O(g(n)) als vanaf een bepaalde waarde van n (soms 0, soms meer) f(n) nooit meer dan een vaste constante keer g(n) is.  Dus: 3n 2 = O(n 2 )  Nog meer voorbeelden (zometeen)  Feitelijk: laat de constante factor weg, en laat langzamer groeiende functies weg Datastructuren

5 5 Voorbeelden  n 2 + 4n + 6  log n 3  12n + log n + 3  r 2 – 10  2 3n+4  15 Datastructuren

6 6 Voorbeelden  n 2 + 4n + 6 = O(n 2 )  log n 3 = 3 log n = O(log n)  12n + log n + 3 = O(n)  r 2 – 10 = O(r 2 )  2 3n+4 = 16 * 2 3n = O(2 3n )  Of: … = O(8 n )  15 = O(1) Datastructuren

7 7 Zoeken van element uit (ongesorteerde) array ZOEK-ELEMENT(x,A) {Input: Een element x en een array A (A loopt van 1 tot lengte(A))} {Output: Een index i zodat A[i] = x of 0 als geen element in A gelijk is aan x} i = 1; while i  lengte(A) do if (x = = A[i]) then return i else i = i + 1; endif enddo; return 0  Schrijf: n = lengte (A)  Iedere iteratie van de loop kost O(1) stappen  Begrensd door constante  Maximaal n iteraties  Totaal: O(n) werk

8 8 Binary search  Vorige keer: zoeken van element in gesorteerde array:  Binary search  Twee variabelen: onder en boven  Invariant: Als er een i is met A[i] == x, dan onder  i  boven  Iedere loopslag wordt het boven – onder ongeveer half zo groot: dus ongeveer log n iteraties van de loop

9 9 Tijd van binary search  Iedere keer wordt het stuk waar je kijkt ongeveer half zo lang  Je kan log n (grondtal 2) keer doormidden delen en dan heb je een stuk van lengte 1  Dus O(log n) stappen  Nette wiskundige analyse zometeen

10 10 Binary search Pseudocode  {Input: Gesorteerde array A[1 … n], element x}  {Output: index i met A[i] == x, and 0 als zo’n i niet bestaat}  onder = 1; boven = n;  while (onder < boven) do  mid =  (onder+boven)/2   if (A[mid] < x) then onder = mid+1 else boven = mid  if (A[onder] == x) then return onder else return 0 (zit er niet in)  Iedere iteratie van de loop kost O(1) werk  O(log n) iteraties  Maximaal log n + 1  Totaal O(log n) werk

11 11 O(log n) grens voor Binary search  Lengte van deel waar we op werken: boven – onder + 1  Inductie hypothese: Nadat (boven – onder + 1)  2 i vinden hooguit i – 1 iteraties van de while-loop plaats.  Bewijs met inductie:  Basisgeval: i = 1: onder < boven geldt niet, dus 0 iteraties  Als i > 1: na 1 iteratie is (boven – onder + 1) 2 i-1 daarna vinden nog (Inductie Hypothese) hooguit i-2 iteraties plaats, totaal dus hooguit i-1  Elke iteraties kost O(1) tijd, dus Binary Search kost O(log n) tijd

12 12 Sorteeralgoritmen  Aantal algoritmen om te sorteren  Analyse: insertion sort  Simpel algoritme: bubble sort  Sneller: merge sort (ritsen)  Ook snel: heapsort (met datastructuur: heap)  In de praktijk heel snel: (randomized) quicksort

13 13 Insertion sort  Sorteeralgoritme, met volgende idee:  Voeg steeds één element toe op de goede plek  We hebben een steeds groter goedgesorteerd deel  Array A loopt van 1 t/m lengte(A) INSERTION-SORT(A) for j = 2 to lengte(A) do key = A[j] {voeg A[j] op de goede plek in} i = j – 1; while i > 0 and A[i] > key do A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key Datastructuren

14 14 Tijdsanalyse van INSERTION-SORT 1  Eerst dit:  Hoeveel stappen kost één slag van de loop voor 1 bepaalde waarde van j ?  Weer een loop.  Elke doorgang door de loop kost iets van 8 elementaire stappen  Deze loop gaan we hooguit j keer rond  Nog eens 6 operaties buiten de loop  Dus 8 j + 6 operaties voor deze slag Datastructuren INSERTION-SORT(A) for j = 2 to lengte(A) do (*) key = A[j] {voeg A[j] op de goede plek in} i = j – 1; while i > 0 and A[i] > key do A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key (**)

15 15 Tijdsanalyse van INSERTION-SORT 2  Hoeveel stappen kost één slag van de loop voor een bepaalde waarde van j ?  8 j + 6 of minder  We doen dit voor j=2, 3, …, tot lengte(A)=n  Totaal: constante keer n 2  Formeel bewijs zometeen  Schrijven we als O(n 2 ) Datastructuren INSERTION-SORT(A) for j = 2 to lengte(A) do (*) key = A[j] {voeg A[j] op de goede plek in} i = j – 1; while i > 0 and A[i] > key do A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key (**)

16 16 Voor en nadelen insertion-sort  Voordelen  Eenvoudig  Geen extra geheugen  Snel als rij al gesorteerd  Nadelen  Langzaam: O(n 2 )

17 17 Sommaties I  Hoeveel is: ?  Eerst eens: hoeveel is … + n?  Strafwerk van Gauss: reken …+100 uit.  Een minuutje later…

18 18 Gauss  … =  (1+100) + (2+99) + … + (50+51) =  50 * 101 =  5050  Net zo: … + n = (n+1)* n / 2

19 19 Bewijzen met inductie  Bewijsmechanisme: Inductie  Hoe doe je dat: 1. Stel een inductiehypothese op 2. Laat zien dat de IH waar is voor het basisgeval (bijvoorbeeld n = 1) 3. Laat zien dat als de IH geldt voor (integer) waarden kleiner dan n, dan geldt de IH ook voor n 4. Klaar: je kan concluderen dat de IH geldt voor alle integer n  1

20 20 Inductiebewijs sommatie    1  i  n i = (n+1)*n / 2 1. De stelling geldt voor n = 1, want 1 = 2 * 1/2 2. Stel de bewering is waar t/m n-1.   1  i  n i = n+   1  i  n-1 i = (vanwege Inductie Hypothese) n + n * (n – 1)/2 = (eenvoudige wiskunde) (n+1)*n / 2

21 21 En hoe doen we dan

22 22 Opmerkingen  Je hoeft voor een O-analyse van de tijd van een algoritme niet het helemaal precieze aantal operaties te tellen: constant is constant  Dus:  Key = a[4] + key^2 / 3 ... Is O(1) operaties  Aanroepen van libraries zijn soms meer dan O(1) werk, ook al staat er 1 opdracht! Datastructuren

23 23 Bubblesort  Eenvoudig sorteeralgoritme  repeat  change = false;  for i=1 to n-1 do if (a[i] > a[i+1]) then –verwissel a[i] en a[i+1] van plaats –change = true  until (change == false) Verwissel: hulp = a[i]; a[i] = a[i+1]; a[i+1] = hulp; Verwissel: hulp = a[i]; a[i] = a[i+1]; a[i+1] = hulp; Correct? Hoe snel?

24 24 Correctheid en tijd bubble sort  Als we klaar zijn is de array gesorteerd; we hebben steeds een permutatie van de input  Terminatie? Ja, want  Na i keer de hoofdloop gedaan te hebben staan op posities n - i +1, n – i +2, …, n de i grootste getallen in de array Bewijzen we zometeen  Dus: na hooguit n keer de hoofdloop te doen, is het array gesorteerd en zijn we klaar

25 25 Inductiebewijs Bubble sort  Inductie hypothese: Voor alle i: 0  i  n: Na i keer de hoofdloop gedaan te hebben staan op posities n - i +1, n – i +2, …, n de i grootste getallen in de array  Klopt als i = 0  Stel waar voor i – 1, dan …

26 26 Tijd  Verwissel: O(1)  Binnenste deel: O(1)  For: n keer O(1): O(n)  Totaal: n keer O(n):  O(n 2 )  Er zijn ook inputs waar zo’n n 2 stappen gedaan worden, bijv.: het omgekeerde van een gesorteerde array (10, 9, 8, 7, 6, 5, 4, 3, 2, 1)  repeat  change = false;  for i=1 to n-1 do if (a[i] > a[i+1]) then –verwissel a[i] en a[i+1] van plaats –change = true  until (change == false)

27 27 Mergesort

28 28 Divide and conquer  Divide et impera  Verdeel en heers  Politiek / militaire strategie  Algorithmische techniek Datastructuren

29 29 Mergesort  Algoritmische methode: divide and conquer (verdeel en heers)  Splits probleem in deelstukken  Los elk deelstuk afzonderlijk op  Combineer oplossing van deelstukken  Mergesort gebruikt divide and conquer strategie  Sorteer eerst, recursief de 1e helft van de array  Sorteer daarna, recursief, de 2e helft van de array  Voeg de twee gesorteerde helften samen door een soort van ‘ritsen’

30 30 Merge-sort I Mergesort(A, p, r)  {Input: array A, integers p, r, met 1 p  r  lengte(A)}  {Output: A[p..r] is gesorteerd en bevat dezelfde elementen als A[p..r] in input}  If (p  r) then doe niets  else  midden =  (p+r)/2   Mergesort(A,p, midden);  Mergesort(A,midden+1,r);  Merge(A,p,midden,r); {“Rits” de twee stukken in elkaar”}

31 31 Merge(A,p,q,r) (deel 1)  {Input: A[p…q] is gesorteerd, en A[q+1…r] is gesorteerd}  {Output: A[p…r] is gesorteerd}  n1 = q – p +1;  n2 = r – q;  Maak een array L[1…n1+1];  Maak een array R[1..n2+1];  for i=1 to n1 do L[i] = A[p+i – 1];  for j=1 to n2 do R[j] = A[q+j];  (rest komt zometeen) Eerst copieren in arrays L en R Eerst copieren in arrays L en R Eentje extra voor stootblokken

32 32 Merge deel 2  n1 = q – p +1;  n2 = r – q;  Maak een array L[1…n1+1];  Maak een array R[1..n2+1];  for i=1 to n1 do L[i] = A[p+i – 1];  for j=1 to n2 do R[j] = A[q+j];  L[n1+1] = MAXINT; {Stootblok (sentinel)}  R[n2+1] = MAXINT; {Stootblok}

33 33 Merge deel 2  n1 = q – p +1; n2 = r – q;  Maak arrays L[1…n1+1] en R[1..n2+1];  for i=1 to n1 do L[i] = A[p+i – 1];  for j=1 to n2 do R[j] = A[q+j];  L[n1+1] = MAXINT; {Stootblok}  R[n2+1] = MAXINT; {Stootblok}  pleklinks = 1;  plekrechts = 1;  for k = p to r do  {Vind het element op positie k in A}  if (L(pleklinks)  R(plekrechts)) then A[k] = L(pleklinks); pleklinks ++; else A[k] = R[plekrechts); plekrechts ++;

34 34 Correctheid merge  Invariant  Aan het begin van de for-loop gelden: A[p…k-1] bevat de k-p kleinste elementen uit L[1..n1+1] en R[1..n2+1] A[p…k-1] is gesorteerd L[pleklinks] is het kleinste element in L dat niet teruggezet is naar A r[plekrechts] is het kleinste element in R dat niet teruggezet is naar A  Invariant geldt initieel, en blijft gelden  Bij terminatie: k = r+1; en dus...

35 35 Tijd van mergesort  Wat is de tijd van een enkele mergeoperatie?  Als we twee stukken van lengte r mergen: O(r) (want…)  Analyse van mergesort hier wat informeler – kijk naar de “berekeningsboom”

36 36 log n niveau’s

37 37 Tijd van mergesort  O(n log n)

38 38 Quicksort  Verdeel en heers paradigma  Idee is:  Kies een element uit de array, zeg x  Splits de array in drie stukken: Alles in 1 e stuk is  x 2 e stuk is het element x Alles in 3 e stuk is  x (of >)  Sorteer recursief het eerste stuk  Sorteer recursief het derde stuk  Klaar!

39 39 Opmerking  In onze beschrijving gaan 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

40 40 PARTITION Quicksort: Eén Datastructuren

41 41 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

42 42 Partition  Code in boek is subtiel pivot Allemaal  Allemaal  Gebied waar we nog aan werken ij-1p r i+1j

43 43 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]  pivot 2. Als i+1  k  j – 1, dan A[k]  pivot 3. Als k=r, dan A[k]=pivot

44 44 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]  pivot 2. Als i+1  k  j – 1, dan A[k]  pivot 3. Als k=r, dan A[k]=pivot  Merk op:  Initieel geldt invariant: triviaal  Invariant blijft gelden  Bij terminatie …

45 45 Partition na de loop  En dan verwisselen we A[i+1] en A[r] Allemaal  Allemaal  i p r i+1 Allemaal  Allemaal  i+1 pr

46 46 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

47 47 CODE EN EERSTE ANALYSE Quicksort: Twee Datastructuren

48 48 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)

49 49 Allemaal  Allemaal  q r r p p

50 50 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: (n 2 ) stappen

51 51 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) = (n 2 ) Andere constantes Met inductie naar n

52 52 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

53 53 log n niveau’s

54 54 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

55 55 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 log 10/9 n = (lg n) lagen  Per laag (n) dus in zo’n geval eveneens (n lg n)  Maar … hoe vaak gebeurt dat?

56 56 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)

57 57 RANDOMIZED QUICKSORT Drie Datastructuren

58 58 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

59 59 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 kans om als pivot-element gebruikt te worden

60 60 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)

61 61 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”?

62 62 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)

63 63 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)

64 64 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)

65 65 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

66 66 Tellerij klaar  Hoe vaak kan je n met ¾ vermenigvuldigen totdat je onder de 1 bent?  log 4/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 log 4/3 n = O(log n) keer  Dus: verwachtte tijd Quicksort O(n log n)  Andere analyse (wel in sheets, niet vandaag):  2n ln n

67 67 Analyse Randomized-Partition  Slechtste geval: weer (n 2 )  T(n) = max 0 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

68 68 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)

69 69 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)

70 70 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

71 71 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

72 72 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=0 n-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=0 n-1 D(k) voor n>0

73 73 - Deze hadden we Maal n nemen Zelfde vergl. voor n-1 Vergelijkingen aftrekken Na vereenvoudigen

74 74 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 s n waarbij s n = (a n-1 a n-2 …a 1 )/(b n b n-1 …b 2 ) als a n D(n)=b n D(n-1)+c n Want dan is s n b n =s n-1 a n-1 En dan krijg je voor E(n)=s n a n D(n) de formule E(n)=E(n-1)+s n c n Wat een somformule voor E en daarna voor D geeft…

75 75 D(0)=0 nD(n) = (n+1)D(n-1)+ 2n a n = n b n = n+1 c n = 2n : dit hadden we Definitie toepassen: Alles maal s n : Def.: (*) en (**) geven: (*) (**)

76 76 dus We hadden dus Want E(0)=0

77 77 Aantal vergelijkingen randomized quicksort Randomized-Quicksort doet verwacht ongeveer 2(n+1)ln n vergelijkingen

78 78 ADT versus Datastructuur  Datastructuur  is een systematische manier van organiseren van data en toegang verlenen tot diezelfde data.  Abstract data type  is een model van een datastructuur waarin gespecificeerd is: type van de data operaties ter ondersteuning van de datastructuur de types van de parameters van deze operaties  Een abstract data type concentreert zich op functionaliteit, niet op tijd.  Vandaag: Heap (is ADT), Array-implementatie van Heap Datastructuren

79 79 Heap  “Hoop”, zoals in “een steenhoop”  Datastructuur, gebruikt voor sorteren en priority queue  Een heap is eigenlijk een boom, maar kan heel efficient in een array worden weergegeven  Datastructuren voor “echte” bomen komen later

80 80 Heap  “Bijna volledige binaire boom”  Vervult de “heap-eigenschap”  Wat bedoelen we hiermee?

81 81 Binaire boom  Binaire boom:  Iedere knoop heeft 0, 1 of 2 kinderen  Volledige binaire boom:  Behalve op het onderste niveau heeft elke knoop 2 kinderen  Een knoop kan hebben:  Ouder (PARENT)  Linkerkind (LEFT)  Rechterkind (RIGHT)

82 82 Bijna volledige binaire boom  Alle niveau’s helemaal gevuld, behalve ‘t onderste dat een eindje van links af gevuld is, en daarna niet meer  Volledige bb mag ook

83 83 Twee termen  Diepte van knoop: afstand naar wortel  Hoogte van knoop x: maximale afstand naar blad onder x

84 84 Heap-eigenschap  Elke knoop x in de heap heeft een waarde A[x]  Max-heap eigenschap: voor alle knopen i (behalve natuurlijk de wortel van de boom) geldt: A[PARENT(i)]  A[i]  Min-heap eigenschap: voor alle knopen i (behalve natuurlijk de wortel van de boom) geldt: A[PARENT(i)] A[i]

85 Max-heap

86 86 Heapsort  Gebruikt de Heap datastructuur met implementatie in array  Heap

87 87 Implementatie van een heap

88 88 Implementatie van een heap  Gebruik een array  A[1] is de wortel  A[2], A[3] de achteenvolgende elementen op hoogte 1  A[4], A[5], A[6], A[7] voor hoogte 2,  A[2 r ], … A[2 r+1 -1] voor hoogte r  PARENT(i)  Return  i/2   LEFT(i)  Return 2i;  RIGHT(i)  Return 2i+1;

89 89 Array implementatie  PARENT(i)  Return  i/2   LEFT(i)  Return 2i;  RIGHT(i)  Return 2i+1;

90 90 “Operaties” op Max-Heap  Build-Max-Heap  Maak een heap van een ongeordende array elementen  Max-Heap-Insert  Voeg een nieuw element toe aan een heap  Heap-Extract-Max  Haal het grootste element uit de heap en lever dat op  Heap-Increase-Key  Verhoog de waarde van een element  Heap-Maximum  Lever de waarde van het grootste element op (zonder iets te veranderen)  NB: Notatie boek is wat slordig (verwart ADT en implementatie, maar ik volg ‘m toch)

91 91 Min-heaps  Net als Max-heaps met min en max (etc.) omgedraaid

92 92 Als we deze operaties geimplementeerd hebben, kunnen we sorteren  Build-Max-Heap(A)  For i=0 to n-1 do  B[n-i] = Heap-Extract-Max(A)

93 93 Belangrijke subroutine: Max-Heapify  Max-heapify(A,i)  {Input-aanname: de binaire boom met wortel LEFT(i) en de binaire boom met wortel RIGHT(i) zijn max-heaps}  {Output: permutatie, zodat de binaire boom met wortel i is een max-heap}

94 Idee: als i groter (  ) is dan beide kinderen: OK, klaar Anders, verwissel met grootste kind en ga dan corrigeren op de plek van ‘t grootste kind

95

96 96 Max-heapify Max-Heapify(A,i)  links = LEFT(i)  rechts = RIGHT(i)  if (links  heap-size[A] and A[links] > A[i])  then grootste = links  else grootste = i  if (rechts  heap-size[A] and A[rechts] > A[grootste])  then grootste = rechts  if (grootste  i)  then  Verwissel A[i] en A[grootste]  Max-Heapify(A,grootste)

97 97 Analyse Max-Heapify  Correct?  Looptijd: O(diepte van i)  De diepte van een knoop is nooit meer dan log n, als heap-size(A)=n  Dus: O(log n)

98 98 Build-Max-Heap Build-Max-Heap(A)  {Input: ongesorteerde rij getallen A[1…lengte(A)]}  {Output: A is een permutatie van input die aan max-heap eigenschap voldoet}

99 99 Build-Max-Heap Build-Max-Heap(A)  {Input: ongesorteerde rij getallen A[1…lengte(A)]}  {Output: A is een permutatie van input die aan max-heap eigenschap voldoet}  heap-size[A] = lengte(A);  for i=  lengte(A)/2 downto 1 do  Max-Heapify(A,i) That’s all en ‘t klopt ook nog! That’s all en ‘t klopt ook nog!

100 100 Correctheid Build-Max-Heap  Invariant: aan het begin van de for-loop is elke knoop i+1, … n de wortel van een max-heap  Initieel: klopt, want boompjes van 1 knoop  Onderweg: vanwege Max- Heapify… (bespreken details)  Terminatie: leuk, want i=0, dus knoop 1 is wortel van max-heap, dus hele array is max-heap for i=  lengte(A)/2  downto 1 do Max-Heapify(A,i)

101 101 Tijdsanalyse Build-Max-Heap  Eenvoudige analyse geeft O(n log n)  Voor iedere i tussen 1 en n/2 doen we O(log n) werk  Meer precieze analyse geeft O(n)  Werk voor knoop i is O(hoogte(i))  De hoogte van de boom is  log n (basis 2)  Er zijn n h+1 knopen met hoogte h in de boom  Gebruik dat Details op bord

102 102 Heapsort  Build-Max-Heap(A)  for i = lengte(A) downto 2 do  {A[1] is het maximum}  {A[1…heap-size[A]} is een heap, de elementen na heap-size[A] zijn gesorteerd maar niet langer in de heap}  {Invariant: i = heapsize[A]}  Verwissel A[1] en A[i];  Heapsize[A] --;  Max-Heapify[A];

103 103 Analyse  Correct, want …  O(n log n) tijd want…

104 104 Next:  Andere operaties op heaps ...


Download ppt "1 Datastructuren Sorteren, zoeken en tijdsanalyse College 2."

Verwante presentaties


Ads door Google