1 / 107

Datastructuren Sorteren, zoeken en tijdsanalyse

Datastructuren Sorteren, zoeken en tijdsanalyse. College 2. Plan. O-notatie Bewijzen met inductie Sorteren: analyse van insertion sort Bubble sort Merge Sort Quicksort Heapsort (volgende keer). Zoeken van element in een Array. Ongesorteerde array:

Download Presentation

Datastructuren Sorteren, zoeken en tijdsanalyse

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. DatastructurenSorteren, zoeken en tijdsanalyse College 2

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

  3. Zoeken van element in een Array • Ongesorteerde array: • Linear search: bekijk de elementen tot je ‘t gezochte element tegenkomt of alles gezien hebt • Gesorteerde array: • Linear search: niet het handigste algoritme… • Binary search: veel sneller: steeds de zoekruimte halveren … een aantal keer log n stappen • Er bestaan soms nog slimmere methoden (interpolatie), maar daar hebben we ‘t niet over hier Datastructuren

  4. Tijdgrenzen analyseren • Om wat preciezer over de tijd / snelheid van een algoritme / datastructuur te kunnen praten, introduceren we een notatie: O Datastructuren

  5. 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

  6. “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: 3n2 = O(n2) • Nog meer voorbeelden (zometeen) • Feitelijk: laat de constante factor weg, en laat langzamer groeiende functies weg Datastructuren

  7. Voorbeelden n2 + 4n + 6 log n3 12n + log n + 3 r2 – 10 23n+4 15 Datastructuren

  8. Voorbeelden • n2 + 4n + 6 = O(n2) • log n3 = 3 log n = O(log n) • 12n + log n + 3 = O(n) • r2 – 10 = O(r2) • 23n+4 = 16 * 23n = O(23n) • Of: … = O(8n) • 15 = O(1) Datastructuren

  9. 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; whilei£ lengte(A) do if (x = = A[i]) then return i elsei = 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 Zoeken van element uit (ongesorteerde) array

  10. 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

  11. 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

  12. {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 Binary search Pseudocode

  13. O(log n) grens voor Binary search • Lengte van deel waar we op werken:boven – onder + 1 • Inductie hypothese: Nadat (boven – onder + 1) £ 2ivinden 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)£ 2i-1daarna vinden nog (Inductie Hypothese) hooguit i-2iteraties plaats, totaal dus hooguit i-1 • Elke iteraties kost O(1) tijd, dus Binary Search kost O(log n) tijd

  14. 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

  15. 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; whilei > 0 and A[i] > keydo A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key Datastructuren

  16. 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 INSERTION-SORT(A) for j = 2 to lengte(A) do (*) key = A[j] {voeg A[j] op de goede plek in} i = j – 1; whilei > 0 and A[i] > keydo A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key (**) Datastructuren

  17. Tijdsanalyse van INSERTION-SORT 2 INSERTION-SORT(A) for j = 2 to lengte(A) do (*) key = A[j] {voeg A[j] op de goede plek in} i = j – 1; whilei > 0 and A[i] > keydo A[i+1] = A[i] {schuif eentje op} i = i – 1; A[i+1] = key (**) • 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 n2 • Formeel bewijs zometeen • Schrijven we als O(n2) Datastructuren

  18. Voordelen Eenvoudig Geen extra geheugen Snel als rij al gesorteerd Nadelen Langzaam: O(n2) Voor en nadelen insertion-sort

  19. Sommaties I • Hoeveel is: ? • Eerst eens: hoeveel is 1+ 2+ … + n? • Strafwerk van Gauss: reken 1+2+3+ …+100 uit. • Een minuutje later…

  20. Gauss • 1+2+3+ … + 100 = • (1+100) + (2+99) + … + (50+51) = • 50 * 101 = • 5050 • Net zo: 1+2 + … + n = (n+1)* n / 2

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

  22. Inductiebewijs sommatie • S1 £i£ni = (n+1)*n / 2 • De stelling geldt voor n = 1, want1 = 2 * 1/2 • Stel de bewering is waar t/m n-1.S1 £i£ni = n+ S1 £i£n-1 i = (vanwege Inductie Hypothese)n + n * (n – 1)/2 = (eenvoudige wiskunde) (n+1)*n / 2

  23. En hoe doen we dan

  24. Arithmetische serie • … (aantal)* (eerste plus laatste) / 2 waarbij cj – cj-1 constant is Datastructuren

  25. 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

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

  27. 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

  28. 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 …

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

  30. Mergesort

  31. Divide and conquer • Divide et impera • Verdeel en heers • Politiek / militaire strategie • Algorithmische techniek Datastructuren

  32. 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’

  33. 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”}

  34. 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) Eentje extra voor stootblokken Eerst copieren in arrays L en R

  35. 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}

  36. 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 ++;

  37. 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 ... 

  38. 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”

  39. log n niveau’s

  40. Tijd van mergesort • O(n log n)

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

  42. 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

  43. PArtition Quicksort: Eén Datastructuren

  44. 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

  45. Partition Code in boek is subtiel pivot Allemaal £ Allemaal > r p i i+1 j-1 j Gebied waar we nog aan werken

  46. Pseudocode Partition Partition(A,p,r) pivot = A[r]; i = p – 1; forj = 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: Als p £ k £ i, dan A[k] £pivot Als i+1 £ k £ j – 1, dan A[k] >pivot Als k=r, dan A[k]=pivot

  47. Pseudocode Partition Partition(A,p,r) pivot = A[r]; i = p – 1; forj = 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: Als p £ k £ i, dan A[k] £pivot Als i+1 £ k £ j – 1, dan A[k] >pivot Als k=r, dan A[k]=pivot Merk op: Initieel geldt invariant: triviaal Invariant blijft gelden Bij terminatie …

  48. Partition na de loop En dan verwisselen we A[i+1] en A[r] Allemaal £ Allemaal > r p i i+1 Allemaal £ Allemaal > i+1 p r

  49. Looptijd partition Partition(A,p,r) pivot = A[r]; i = p – 1; forj = 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: Q(r-p+1) Inspectie van loopstructuur

  50. CODE EN EERSTE ANALYSE Quicksort: Twee Datastructuren

More Related