1 Datastructuren Heapsort (2e deel) College 5
2 Vandaag Heaps en Heapsort (eind) Nog sneller sorteren: Ondergrenzen Linair sorteren
3 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)
4 Bijna volledige binaire boom 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 binaire bomen mogen ook (speciaal geval)
5 Termen Wortel Diepte van knoop: afstand naar wortel Hoogte van knoop x: maximale afstand naar blad onder x Zwarte knoop: Diepte 1 Hoogte 2 Zwarte knoop: Diepte 1 Hoogte 2
6 Heaps Elke knoop x in de heap heeft een waarde A[x] Max-heap: Bijna volledige binaire boom met de Max-heap eigenschap: voor alle knopen i (behalve natuurlijk de wortel van de boom) geldt: A[PARENT(i)] A[i] Min-heap: Bijna volledige binaire boom met de Min-heap eigenschap: voor alle knopen i (behalve natuurlijk de wortel van de boom) geldt: A[PARENT(i)] A[i]
Max-heap
Min-heap
9 Heapsort Gebruikt de Heap datastructuur met implementatie in array Heap kan heel goed worden geimplementeerd met een “gewoon” array We hebben een variable heapsize: geeft aan hoeveel elementen in ‘t array tot de heap behoren (1 t/m heapsize zijn heap- elementen) Bij sorteren worden de elementen NA heapsize gebruikt om gesorteerde deel op te slaan (komt)
10 Implementatie van een heap
11 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 Vb komt hierna PARENT(i) return i/2 LEFT(i) return 2i; RIGHT(i) return 2i+1;
12 Array implementatie PARENT(i) return i/2 LEFT(i) return 2i; RIGHT(i) return 2i+1;
13 “Operaties” op Max-Heap Build-Max-Heap Maak een heap van een ongeordende array elementen Gebruikt subroutine: Max-Heapify 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)
14 Build-Max-Heap Maakt van een ongesorteerde array elementen een heap: Datastructuren
15 Max-heap-insert Voegt een element toe aan een max-heap Datastructuren
16 Heap-extract-max Haalt het grootste element uit een max- heap en lever dat op Zorg dat je weer een heap hebt na afloop Output: 16
17 Heap-increase-key Verhoog de waarde van een key en zorg dat je na afloop weer een max-heap hebt Datastructuren
18 Heap-max Geef het grootste element uit de max-heap Verandert verder niets Output: 16
19 Min-heaps Net als Max-heaps met min en max (etc.) omgedraaid
20 Als we deze operaties geimplementeerd hebben, kunnen we sorteren Sorteren-Met-Heap- 1eVersie(A) Build-Max-Heap(A) Maak array B[1…n] for i=0 to n-1 do B[n-i] = Heap-Extract- Max(A) Algoritme hiernaast sorteert; gebruikt extra array B Maar ‘t kan ook zonder extra array (komt straks)
21 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}
Idee: als i groter () is dan beide kinderen: OK, klaar Anders, verwissel i met grootste kind en ga dan corrigeren op de plek van ‘t grootste kind
25 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) Reken uit wie de grootste is: A[i],A[links] of A[rechts]
26 Analyse Max-Heapify Correct? Jazeker! Looptijd: O(hoogte van i) Met wat hulplemma’s O(lg n)
27 Hulplemma’s Een volledige binaire boom met hoogte r heeft 2 r+1 -1 knopen Bewijs: waar als r=0. Als r>0, wortel plus twee deelbomen van diepte r-1 en 1+(2 r -1)+(2 r -1)= 2 r Een bijna volledige binaire boom met hoogte r heeft maximaal 2 r+1 -1 knopen Een heap met n elementen heeft hoogte maximaal lg n .
28 Tijd Max-Heapify O(hoogte van i) = O(lg n)
29 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}
30 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!
31 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) Bij terminatie: fijn, 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)
32 Tijdsanalyse Build-Max-Heap Eenvoudige analyse geeft O(n lg n) Voor iedere i tussen 1 en n/2 doen we O(lg n) werk Meer precieze analyse geeft O(n). Plan: Werk voor knoop i is O(hoogte(i)+1) De hoogte van de boom is lg n (basis 2) Er zijn n h+1 knopen met hoogte h in de boom Gebruik dat
33 Analyse Build-max-heap Werk voor knoop i is O(hoogte(i)+1) De hoogte van de boom is lg n Er zijn maximaal n h+1 knopen met hoogte h in de boom Bewijs met inductie omlaag: als h = lg n dan is er 1 knoop: wortel; voor kleinere h maximaal twee keer zoveel als voor hoogte h+1 Totale werk is …= O(n)
34
35 Heapsort Heapsort(A) 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,1); Sorteert zonder extra geheugen in O(n lg n) tijd
36 Array is ongesorteerde rij elementen Array is heap Array is gesorteerde rij elementen Max-heapify 2e deel heapsort
37 Analyse Correct, want … O(n lg n) tijd want…
38 Heap-Maximum(A) return A[1]; Geef de waarde van het grootste element uit heap A
39 Heap-Extract-Max(A) if heap-size(A)<1 then error else max = A[1]; A[1] = A[heap-size[A]]; heap-size[A] --; Max-Heapify(A,1); return max; Geef de waarde van het grootste element uit A en haal dit element weg Vgl. met stap uit Heap- sort
40 Heap-Increase Key Heap-Increase-Key(A,i,key) if key < A[i] then error else A[i] = key while i>1 and A[parent[i]] < A[i] do Verwissel A[i] en A[parent[i]]; i = parent[i] Verhoog de waarde van element A[i] tot key Verlaging is niet toegestaan; geven we foutmelding Als in boek. Niet zo moeilijk om code te veranderen zodat je ook keys kan verlagen (als Max-Heapify)
42 Heap-Insert Max-Heap-Insert(A,key) heap-size[A]++; A[heap-size[A]] = - Heap-Increase- Key(A,heap-size[A],key) Zolang array A groot genoeg is werkt dit
43 Priority queue Priority queue is Abstract Data Type met volgende operaties: Insert (S, x): voeg element x in verzameling S toe Maximum(S): geef het grootste element uit S Extract-Max(S): geef het grootste element uit S en haal dit uit de verzameling S weg Increase key (S, x, k): verhoog de waarde van x tot k Elementen hebben een waarde uit een totaal geordende verzameling (bijv. ze zijn getallen) Toepassing bijvoorbeeld: taakselectie in multi-user systeem Heap implementeert Priority Queue
44 Heap implementeert Priority Queue Insert: O(lg n) mits oorspronkelijk aangemaakte array groot genoeg Maximum: O(1) Extract-Max: O(lg n) Increase-Key: O(lg n) Snel
45 Hierna Nog sneller sorteren: kan dat??? Ja, maar alleen als er iets bijzonders aan de hand is… (gebruik makend van eigenschappen van de gegevens)