Dynamické datové struktury III. Halda. Tomáš Bayer bayertom@natur.cuni.cz Katedra aplikované geoinformatiky a kartografie, Přírodovědecká fakulta UK. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 1 / 27
Obsah přednášky 1 Halda 2 Operace nad haldou Inicializace Oprava haldy nahoru Oprava haldy dolů Přidání prvku do haldy Nalezení maxima Smazání kořene Třídící algoritmus Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 2 / 27
Halda 1. Halda tzv. Heap. Patří mezi rekurzivní datové struktury, reprezentována binárním stromem. Volnější definice než BST. Varianty: MinHeap: v kořeni minimum, běžná varianta. MaxHeap: v kořeni maximum, použití u prioritní fronty. Vlastnosti min-haldy: Hodnota v každém uzlu menší než v libovolném z potomků. V hladinách 1, x 1 maximální počet prvků n (x) u n (x) u = 2 x 1. V hladině x prvky řazeny co nejvíce vlevo. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 3 / 27
2. Halda, další vlastnosti Vlastnosti: Halda V kořenu minimální prvek, někde v úrovni x maximální prvek. Nalezení minima s konstantní složitostí, nalezení maxima se složitostí O(N). Při vkládání prvku nemusíme měnit tvar stromu, provádíme pouze vzájemné výměny prvků ve stromu. Odpadá nutnost převažovat strom. Implementace haldy: binárním stromem, 1D polem. Varianta 2: Častější (nemění se tvar stromu), nutno však znát horní odhad počtu prvků. Rychlý přístup k prvkům. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 4 / 27
Halda 3. Ukázka haldy 6 10 33 15 19 38 65 25 22 31 30 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 5 / 27
Halda 4. Reprezentace haldy polem Definice: Halda představuje takovou posloupnost prvků h l, h l+1, h l+2,..., h r, že pro každý index i = l,..., r/2 platí h i h 2i h i h 2i+1. Ukázka: Halda definována posloupností h 1, h 2,..., h n, kde i = n/2. Kořen stromu h 1, h 2 levý potomek, h 3 pravý potomek. Levý potomek uzlu h 2 je h 4, pravý potomek je h 5, atd. L potomci sudý index, P potomci lichý index. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 6 / 27
Halda 5. Ukázka haldového stromu h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 h13 h14 h15 h[i] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 h i - h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 h 10 h 11 h 12 h 13 h 14 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 7 / 27
Halda 6. Reprezentace haldy polem, důsledky Z důvody neměnnosti tvaru stromu výhodná implementace polem. Vztah mezi pořadovým číslem uzlu h i a indexem uzlu h[i] v poli h i h[i]. Vztah mezi prvkem h[i] a rodičem r r = h[i/2]. Vztah mezi prvkem h[i] a levým potomkem l l = h[2i]. Vztah mezi prvkem h[i] a pravým potomkem p p = h[2i+1]. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 8 / 27
7. Operace nad heapem Operace nad heapem: inicializace heapu (Init): O(1); přidání prvku do heapu (Insert): O(log(N)). oprava heapu (Heapifying): O(log(N)). nahoru: fixheapup dolů: fixheapdown, nalezení max: O(N), velmi neefektivní! smazání minima: O(log(N)). tisk: O(N). Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 9 / 27
Inicializace 8. Reprezentace haldy a inicializace Datová položka n uchovává aktuální velikost heapu. Velikost haldy inicializována na hodnotu maxn představující horní odhad velikosti množiny. Složitost O(1). class Heap { int n; double [] h; void init(int maxn){ n = 0; h = new [] h(maxn); Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 10 / 27
9. Oprava haldy nahoru Oprava haldy nahoru Pohyb haldou od uzlu U směrem ke kořeni haldy, nemá vliv na potomky U. Stromová reprezentace: Pokud předchůdce P uzlu U má vyšší hodnotu, prohodíme U P. Pokračujeme v předchůdci U = P, dokud U není kořen. Reprezentace polem: Pokud prvek [i/2] má menší hodnotu než prvek [i], prohodíme [i/2] [i]. Pokračujeme v předchůdci i = i/2 dokud i > 1. public void fixheapup(int i) { while (i > 1 && (h[i / 2] > h[i])) { //Opakuj pro predchudce double temp = h[i / 2]; //Prohozeni s pouzitim h[i / 2] = h[i]; //lokalni promenne h[i] = temp; i = i / 2; //Jdi na rodice Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 11 / 27
10. Ukázka opravy haldy nahoru Oprava haldy nahoru 6 19 33 15 30 38 65 25 22 31 10 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 12 / 27
Oprava haldy nahoru 11. Ukázka opravy haldy nahoru (30<->10) 6 19 33 15 10 38 65 25 22 31 30 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 13 / 27
Oprava haldy nahoru 12. Ukázka opravy haldy nahoru (10<->19) 6 10 33 15 19 38 65 25 22 31 30 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 14 / 27
Oprava haldy dolů 13. Oprava haldy dolů Pohyb haldou od uzlu U směrem od kořene k listům haldy, nemá vliv na předchůdce U. Stromová reprezentace: Najdi následníky uzlu U: V L, V P. Pokud V P < V L, následník V = V P, jinak V = V L (přidáváme do menšího). Pokud U > V, prohod U V, jinak ukonči. Pokračuj v prohozeném vrcholu, dokud nedosáhneme listu. Reprezentace polem: Najdi následníky uzlu [i]: [2 i], [2 i + 1]. Pokud [2 i + 1] < [2 i], následník [k] = [2 i + 1], jinak [k] = [2 i] (přidáváme do menšího). Pokud [i] > [k], prohod [i] [k] jinak ukonči. Pokračuj v prohozeném vrcholu, dokud nedosáhneme listu Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 15 / 27
Oprava haldy dolů 14. Algoritmus pro opravu haldy dolů public void fixheapdown(int i, int n) { int k; while (2 * i <= n) { k = 2 * i; //Levy potomek if ( h[k + 1] < h[k]) //Porovnani L a P potomka { k++; //Index ukazuje na mensiho potomka if (h[i] > h[k]) //Nesplneny podminky, prohodit { double temp = h[i]; h[i] = h[k]; h[k] = temp; else break; //Ukonceny podminky, nepokracuj i = k; //Pokracuj od prohozeneho potomka Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 16 / 27
15. Ukázka opravy haldy dolů Oprava haldy dolů 6 19 33 15 30 38 65 18 22 31 32 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 17 / 27
Oprava haldy dolů 16. Ukázka opravy haldy dolů (19<->15) 6 15 33 19 30 38 65 18 22 31 32 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 18 / 27
Oprava haldy dolů 17. Ukázka opravy haldy dolů (18<->19) 6 15 33 18 30 38 65 19 22 31 32 45 54 85 93 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 19 / 27
Přidání prvku do haldy 18. Přidání prvku do haldy Složitost O(log(N)). Nevhodná konfigurace vstupních dat: v každém kroku přidáváme největší prvek. V takovém případě musí být opravován strom ke kořeni. Postup: Nový uzel s hodnotou x vytvořen na poslední hladině co nejvíce vpravo. Oprava haldy nahoru U. void add (double item) { n++;//zvetseni heapu o 1 h[n] = item; fixheapup(h, n); //Oprav heap nahoru do akt. pozice Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 20 / 27
19. Ukázka budování haldy Přidání prvku do haldy 3 1 3 1 3 1 1 1 3 5 3 5 3 5 6 6 2 1 1 1 2 5 2 5 2 5 6 3 6 3 9 6 3 9 4 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 21 / 27
Nalezení maxima 20. Nalezení maxima v haldě Maximum se nachází v některém z listu. Z definice heapu nevyplývá, v kterém listu bude ležet. Nutno projít všechny listy, tj. posledních n/2 1 prvků: h[n/2],..., h[n 1]. Složitost operace O(n), překvapivě neefektivní oproti BST. public double findmax() { double max = h[n/2]; for (int i=n/2 + 1;i < n; i++) if (h[i] > max) max = h[i]; return max; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 22 / 27
Smazání kořene 21. Smazání minima Minimum se nachází v kořeni, provádíme smazání kořene. Důsledkem zmenšení haldy o jeden prvek. Složitost O(log(N)). Postup: Do kořene zkopíruj prvek z poslední úrovně nejvíce vpravo: [1] = [n]. Oprava haldy z vrchu od kořene: fixheapdown(); void delmin(){ h[1] = h[h.length()-1]; fixheapdown(h, 1); //Oprav heap od korene n--; Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 23 / 27
Třídící algoritmus 22. Heap Sort Probíhá nad vybudovanou haldou, triviální implementace. Opakuj, dokud halda neobsahuje pouze kořen: Prohození kořene (minima haldy) s prvkem haldy nejnižší úrovně nejvíce vpravo. Oprava haldy dolů (v kořeni není minimum). Zkrácení haldy o prvek nejnižší úrovně nejvíce vpravo. Nad polem snadno algoritmizovatelné. Opakuj, dokud n > 1 Prohodíme h[1] a h[n]. Provedeme opravu haldy dolů z kořene. Dekrementujeme n. První výběr: nejmenší prvek, druhý výběr: druhý nejmenší prvek, atd. Jsou řazeny za koncem zkracované haldy sestupně. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 24 / 27
23. Ukázka činnosti algoritmu Třídící algoritmus 1 5 2 2 4 2 4 3 4 6 3 9 5 6 3 9 1 6 5 9 1 9 3 9 3 4 5 4 5 4 6 5 2 1 6 9 2 1 6 3 2 1 4 6 5 5 9 5 9 6 9 ; 6 3 2 1 4 3 2 1 4 3 2 1 Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 25 / 27
24. Algoritmus Heap Sort Třídící algoritmus Pouze třídící procedura: Vlastnosti algoritmu: while (n > 1) { double temp = h[1]; //Vem nejmensi prvek h[1] = h[n]; //Prohod s poslednim h[n] = temp; n--; //Zkrat heap o 1 fixheapdown(h, 1, n); Algoritmus má složitost O(N lg 2 N). Asi o 20% pomalejší než Merge Sort a o 50% pomalejší než Quick Sort. Použití pro hledání k tého nejmenšího prvku. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 26 / 27
25. Zdrojový kód (celek) Třídící algoritmus public void heapsort(double[] x) { int i = 1, n = x.length; double[] h = new double[n + 1]; //Heap o jeden prvek delsi for (int k = 0; k < n; k++) //Pridej vsechny prvky,oprav heap { h[i] = x[k]; //Pridej do heapu fixheapup(h, i); //Oprav heap zdola i++; //Inkrementuj i while (n > 1) { double temp = h[1]; //Vem nejmensi prvek h[1] = h[n]; //Prohod s poslednim h[n] = temp; n--; //Zkrat heap fixheapdown(h, 1, n); Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované Dynamické geoinformatiky datové struktury a kartografie, III. Přírodovědecká fakulta UK.) 27 / 27