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 Vandaag  Medelingen over werkcollege  O-notatie  Binary search  Sorteren: analyse van insertion sort  Bubble sort  Merge Sort  Heapsort

3 3 Werkcollege  Groepen:  We werken met vier (en dus geen 5) groepen  We gebruiken de zalen van groepen 2, 3, 4 en 5  Kies een zaal/groep (afhankelijk van drukte), en probeer steeds naar dezelfde groep te gaan  We beginnen zometeen  Opgaven staan online maar worden ook tijdens het werkcollege uitgereikt

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

5 5 “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))  Intuitie: 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

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

7 7

8 8 Zoeken in een gesorteerde rij  Array met elementen A[1], …, A[n]  Gegeven een x, is er een i met A[i] == x, en zo ja, welke i?  We zagen al een algoritme dat dit oplost in O(n) tijd: bekijk de elementen van 1 t/m n totdat je x tegenkomt of alles bekeken hebt  Als de rij getallen gesorteerd is kan het sneller met een simpel maar belangrijk principe: binary search  Dus: neem aan: A[1]  A[2]  A[3]  …  A[n-1]  A[n]

9 9 Binary search  Idee: houdt twee variabelen bij onder en boven, zodat x, als x in A zit, “tussen” onder en boven zit  Invariant: als er een i is met A[i] == x, dan onder  i  boven

10 10 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 komt later

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

12 12 Sorteeralgoritmen  Aantal algoritmen om te sorteren  Staart vorige keer: insertion sort  Simpel algoritme: bubble sort  Sneller: merge sort (ritsen)  Ook snel: heapsort (met datastructuur: heap)  In de praktijk heel snel: 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  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 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?

18 18 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  Dus: na hooguit n keer de hoofdloop te doen, is het array gesorteerd en zijn we klaar

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

20 20 Mergesort

21 21 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’

22 22 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”}

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

24 24 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}

25 25 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 ++;

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

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

28 28 log n niveau’s

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

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

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

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

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

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

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

36 36 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]

37 37 16 14 8 241 7 10 93 Max-heap

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

39 39 Implementatie van een heap 16 14 8 241 7 10 93 1 2 3 4 5 6 7 8 9 1614108793241

40 40 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;

41 41 Array implementatie  PARENT(i)  Return  i/2   LEFT(i)  Return 2i;  RIGHT(i)  Return 2i+1; 16 14 8 241 7 10 93 1 2 3 4 5 6 7 8 9 1614108793241

42 42 “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)

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

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

45 45 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}

46 46 16 4 8 251 7 10 93 1 2 3 4 5 6 7 8 9 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

47 47 16 4 251 7 10 93 1 2 3 4 5 6 7 8 16 4 251 7 10 93 1 2 3 4 5 6 7 8 8 8

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

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

50 50 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}

51 51 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!

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

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

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

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

56 56 Next:  Andere operaties op heaps  Quicksort


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

Verwante presentaties


Ads door Google