Triedenie výberom: Rozdiel medzi revíziami
(14 medziľahlých úprav od 2 ďalších používateľov nie je zobrazených) | |||
Riadok 6: | Riadok 6: | ||
===Prehľad=== | ===Prehľad=== | ||
− | Heap Sort je triediaci algoritmus, ktorý podobne ako Selection sort, rozeľuje pole na zotriedenú a nezotriedenú časť, pričom nezotriedená časť predstavuje dátovú štruktúru [[Hromada|binárna hromada]]. Celé triedenie spočíva v tom, že si zo vstupného poľa vytvoríme binárnu hromadu a následne postupným vyberaním a mazaním všetkých jej prvkov toto pole utriedime. | + | ''Heap Sort'' je triediaci algoritmus, ktorý podobne ako ''Selection sort'', rozeľuje pole na zotriedenú a nezotriedenú časť, pričom nezotriedená časť predstavuje dátovú štruktúru [[Hromada|binárna hromada]]. Celé triedenie spočíva v tom, že si zo vstupného poľa vytvoríme binárnu hromadu a následne postupným vyberaním a mazaním všetkých jej prvkov toto pole utriedime. |
− | Hromada, ktorú využíva algoritmus Heap Sort, musí spĺňať nasledovné podmienky (ak indexujeme pole od 0): | + | Hromada, ktorú využíva algoritmus ''Heap Sort'', musí spĺňať nasledovné podmienky (ak indexujeme pole od 0): |
− | :1. Vrchol hromady (koreň) je vždy prvý prvok v poli (v našom prípade prvok na 0-tej pozícii). | + | :1. Vrchol hromady (''koreň'') je vždy prvý prvok v poli (v našom prípade prvok na 0-tej pozícii). |
− | :2. Pre ľubovoľný prvok (uzol), uložený na indexe <math>i</math> z intervalu <math> \langle 0 \ ; \ \text{dĺžka} - 1 \rangle </math>, platia nasledovné rovnice: | + | :2. Pre ľubovoľný prvok (''uzol''), uložený na indexe <math>i</math> z intervalu <math> \langle 0 \ ; \ \text{dĺžka} - 1 \rangle </math>, platia nasledovné rovnice: |
:: <math> | :: <math> | ||
\begin{align} | \begin{align} | ||
Riadok 18: | Riadok 18: | ||
\end{align} | \end{align} | ||
</math> | </math> | ||
− | :3. Každý prvok (uzol) v hromade musí mať väčšiu, alebo rovnakú hodnotu ako jeho potomkovia (vlastnosť MAX HEAP - ak triedime pole vzostupne, v opačnom prípade by sme použili MIN HEAP). | + | :3. Každý prvok (''uzol'') v hromade musí mať väčšiu, alebo rovnakú hodnotu ako jeho potomkovia (vlastnosť ''MAX HEAP'' - ak triedime pole vzostupne, v opačnom prípade by sme použili ''MIN HEAP''). |
===Algoritmus Heapify=== | ===Algoritmus Heapify=== | ||
− | [[Súbor:Heapify.png|Vizualizácia algoritmu Heapify: Index i je iteračná premenná (pozri pseudokód). Ľavý a pravý potomok i-teho prvku je označený ako ĽP a PP. Prvky zafarbené na modro vyjadrujú pravú podhromadu i-teho prvku a prvky zafarbené na zeleno vyjadrujú ľavú podhromadu i-teho prvku. Chronlogický postup algoritmu je znázornený číslicami 1 až 3.|699px|náhľad|vpravo]] | + | [[Súbor:Heapify.png|Vizualizácia algoritmu ''Heapify'': Index ''i'' je iteračná premenná (pozri pseudokód). Ľavý a pravý potomok i-teho prvku je označený ako ''ĽP'' a ''PP''. Prvky zafarbené na modro vyjadrujú pravú podhromadu i-teho prvku a prvky zafarbené na zeleno vyjadrujú ľavú podhromadu i-teho prvku. Chronlogický postup algoritmu je znázornený číslicami 1 až 3.|699px|náhľad|vpravo]] |
− | Heapify je kľúčovým podprogramom triediaceho algoritmu Heap Sort, vďaka ktorému vieme efektíve zabezpečiť procedúry: vytvorenie hromady z poľa a zmazanie hromady. | + | ''Heapify'' je kľúčovým podprogramom triediaceho algoritmu ''Heap Sort'', vďaka ktorému vieme efektíve zabezpečiť procedúry: vytvorenie hromady z poľa a zmazanie hromady. |
− | Princíp algoritmu Heapify spočíva v tom, že ak máme i-ty prvok v poli (v kompletnom binárnom strome), ktorého potomkovia tvoria dve samostatné podhromady, potom tieto dve podhromady preusporiadame do jednej hromady, pričom i-ty prvok bude jej vrcholom. | + | Princíp algoritmu ''Heapify'' spočíva v tom, že ak máme i-ty prvok v poli (v kompletnom binárnom strome), ktorého potomkovia tvoria dve samostatné podhromady, potom tieto dve podhromady preusporiadame do jednej hromady, pričom i-ty prvok bude jej vrcholom. |
====Vlastnosti algoritmu==== | ====Vlastnosti algoritmu==== | ||
− | * dátová štruktúra: hromada (reprezentovaná ako: pole) | + | * '''dátová štruktúra:''' hromada (reprezentovaná ako: pole) |
− | * časová zložitosť: lineárna <math>O(n)</math> | + | * '''časová zložitosť:''' lineárna <math>O(n)</math> |
− | * priestorová zložitosť: konštantná <math>O(1)</math> pri iteračnej verzii, <math>O(log(n))</math> pri rekurzívnej verzii | + | * '''priestorová zložitosť:''' konštantná <math>O(1)</math> pri iteračnej verzii, <math>O(log(n))</math> pri rekurzívnej verzii |
====Základné časti algoritmu==== | ====Základné časti algoritmu==== | ||
Riadok 38: | Riadok 38: | ||
====Slovný opis algoritmu==== | ====Slovný opis algoritmu==== | ||
− | Na vstupe prijmeme pole a index i, v ktorom chceme vytvoriť hromadu (Max Heap). Musí byť splnená podmienka, že oba potomkovia i-teho prvku tvoria dve samostatné podhromady. | + | Na vstupe prijmeme ''pole'' a index ''i'', v ktorom chceme vytvoriť hromadu (''Max Heap''). Musí byť splnená podmienka, že oba potomkovia i-teho prvku tvoria dve samostatné podhromady. |
− | Najskôr skontrolujeme, či prvok na indexe i má nejakých potomkov (využijeme rovnice (1) a (2) z časti "Prehľad"). Ak nemá žiadnych potomkov, funkcia skončí, pretože i predstavuje vrchol jednoprvkovej hromady. Ak má práve jedného potomka, tento potomok je zároveň aj jeho maximálnym potomkom. Ak má práve dvoch potomkov, tak porovnáme ich hodnoty a vyberieme z nich maximálneho potomka. Následne skontrolujeme veľkosť maximálneho potomka a jeho rodiča (prvok na indexe i). Ak je rodič väčší, funkcia skončí, pretože želaná hromada už je utvorená. Ak nie, vymeníme rodiča a maximálneho potomka. Ak nastala výmena, musíme skontrolovať ovplyvnenú podhromadu, tj. zopakovať tento sled krokov pre podhromadu, ktorej vrchol bude v maximálnom potomkovi i-teho prvku. | + | Najskôr skontrolujeme, či ''prvok'' na indexe ''i'' má nejakých potomkov (využijeme rovnice (1) a (2) z časti "Prehľad"). Ak nemá žiadnych potomkov, funkcia skončí, pretože ''i'' predstavuje vrchol jednoprvkovej hromady. Ak má práve jedného potomka, tento potomok je zároveň aj jeho maximálnym potomkom. Ak má práve dvoch potomkov, tak porovnáme ich hodnoty a vyberieme z nich maximálneho potomka. Následne skontrolujeme veľkosť maximálneho potomka a jeho rodiča (prvok na indexe ''i''). Ak je rodič väčší, funkcia skončí, pretože želaná hromada už je utvorená. Ak nie, vymeníme rodiča a maximálneho potomka. Ak nastala výmena, musíme skontrolovať ovplyvnenú podhromadu, tj. zopakovať tento sled krokov pre podhromadu, ktorej vrchol bude v maximálnom potomkovi i-teho prvku. |
− | Z hľadiska implementácie môžeme vytvoriť iteračnú aj rekurzívnu verziu. | + | Z hľadiska implementácie môžeme vytvoriť '''iteračnú''' aj '''rekurzívnu''' verziu. |
====Pseudokód==== | ====Pseudokód==== | ||
Riadok 70: | Riadok 70: | ||
:2. Nech: <code>pravy = 2 * i + 2</code> | :2. Nech: <code>pravy = 2 * i + 2</code> | ||
:3. Nech: <code>max = i</code> | :3. Nech: <code>max = i</code> | ||
− | :4. Je <code>lavy < dlzka</code> a zároveň <code>pole[lavy] > pole[ | + | :4. Je <code>lavy < dlzka</code> a zároveň <code>pole[lavy] > pole[max]</code> ? |
::: Ak áno: | ::: Ak áno: | ||
:::::4.1. Nech: <code>max = lavy</code> | :::::4.1. Nech: <code>max = lavy</code> | ||
::: Ak nie: | ::: Ak nie: | ||
:::::4.1. Pokračuj krokom 5. | :::::4.1. Pokračuj krokom 5. | ||
− | :5. Je <code>pravy < dlzka</code> a zároveň <code>pole[pravy] > pole[ | + | :5. Je <code>pravy < dlzka</code> a zároveň <code>pole[pravy] > pole[max]</code> ? |
::: Ak áno: | ::: Ak áno: | ||
:::::5.1. Nech: <code>max = pravy</code> | :::::5.1. Nech: <code>max = pravy</code> | ||
Riadok 90: | Riadok 90: | ||
===Algoritmus Heap Sort=== | ===Algoritmus Heap Sort=== | ||
− | + | ''Heap Sort'' pri triedení vykonáva dve základné úlohy: Vytvorenie maximálnej binárnej hromady zo vstupného poľa a postupné mazanie jednotlivých prvkov z hromady. Pri oboch procedúrach využíva algoritmus ''Heapify''. | |
====Vlastnosti algoritmu==== | ====Vlastnosti algoritmu==== | ||
− | * vhodný pre dátové štruktúry: pole | + | * '''vhodný pre dátové štruktúry:''' pole |
− | * časová náročnosť: vždy linearitmická <math> O(n\log(n)) </math>, vďaka ktorej dokáže efektívne triediť veľmi veľké polia | + | * '''časová náročnosť:''' vždy linearitmická <math> O(n\log(n)) </math>, vďaka ktorej dokáže efektívne triediť veľmi veľké polia |
− | [[Súbor:HeapSort.png|Vizualizácia priebehu algoritmu Heap Sort: Algoritus je znázornený pomocou poľa, ktoré triedime a binárnej hromady, ktorú dané pole reprezentuje. Indexy i a j sú sú iteračné premenné (pozri pseudokód). Indexy ľavého a pravého potomka i-teho prvku sú označené ako ĽP a PP. Vrchol celej hromady je označený ako V. Prvky zafarbené na modro vyjadrujú pravú podhromadu i-teho prvku a prvky zafarbené na zeleno vyjadrujú ľavú pohromadu i-teho prvku. Nevyfarbené prvky vyjadrujú prvky, ktoré boli zmazané. Chronologický priebeh je označený číslicami 1 až 12. |500px|náhľad|vpravo]] | + | [[Súbor:HeapSort.png|Vizualizácia priebehu algoritmu ''Heap Sort'': Algoritus je znázornený pomocou ''poľa'', ktoré triedime a binárnej hromady, ktorú dané pole reprezentuje. Indexy ''i'' a ''j'' sú sú iteračné premenné (pozri pseudokód). Indexy ľavého a pravého potomka i-teho prvku sú označené ako ''ĽP'' a ''PP''. Vrchol celej hromady je označený ako ''V''. Prvky zafarbené na modro vyjadrujú pravú podhromadu i-teho prvku a prvky zafarbené na zeleno vyjadrujú ľavú pohromadu i-teho prvku. Nevyfarbené prvky vyjadrujú prvky, ktoré boli zmazané. Chronologický priebeh je označený číslicami 1 až 12. |500px|náhľad|vpravo]] |
− | * priestorová náročnosť: konštantná <math>O(1)</math> pri iteračnej verzii, logaritmická <math>O(\log(n))</math> pri rekurzívnej verzii. | + | * '''priestorová náročnosť:''' konštantná <math>O(1)</math> pri iteračnej verzii, logaritmická <math>O(\log(n))</math> pri rekurzívnej verzii. |
− | * druh triedenia: triedenie výberom (komparačný algoritmus) | + | * '''druh triedenia:''' triedenie výberom (komparačný algoritmus) |
− | * stabilita triedenia: nestabilný | + | * '''stabilita triedenia:''' nestabilný |
− | * miesto triedenia: vnútorné triedenie | + | * '''miesto triedenia:''' vnútorné triedenie |
====Základné časti algoritmu==== | ====Základné časti algoritmu==== | ||
Riadok 109: | Riadok 109: | ||
====Slovný opis==== | ====Slovný opis==== | ||
=====Vytvorenie hromady===== | =====Vytvorenie hromady===== | ||
− | Pri vytváraní hromady využijeme algoritmus Heapify, pričom hromadu vytvoríme spôsobom zospodu na vrch. | + | Pri vytváraní hromady využijeme algoritmus ''Heapify'', pričom hromadu vytvoríme spôsobom zospodu na vrch. |
− | Najskôr si určíme rodiča posledného potomka. Využijeme rovnicu (3) z časti | + | Najskôr si určíme rodiča posledného potomka. Využijeme rovnicu (3) z časti "Prehľad", ktorú si jemne upravíme: |
<center><math> \text{posledný rodič:} \ \ i = \left \lfloor \frac{\text{posledný index } - \ 1}{2} \right \rfloor = \left \lfloor\frac{\text{dĺžka } - \ 2}{2} \right \rfloor = \left \lfloor \frac{\text{dĺžka}}{2}\right \rfloor - 1 </math></center> | <center><math> \text{posledný rodič:} \ \ i = \left \lfloor \frac{\text{posledný index } - \ 1}{2} \right \rfloor = \left \lfloor\frac{\text{dĺžka } - \ 2}{2} \right \rfloor = \left \lfloor \frac{\text{dĺžka}}{2}\right \rfloor - 1 </math></center> | ||
− | Následne zavoláme Heapify na podhromadu s vrcholom na indexe i. Potom postupne zmenšujeme index i o 1 a opakovane naňho voláme Heapify až do chvíle, kým neprídeme na začiatok poľa. Touto procedúrou preusporiadavame spodné jednoprvkové podhromady do 3-prvkových | + | Následne zavoláme ''Heapify'' na podhromadu s vrcholom na indexe ''i''. Potom postupne zmenšujeme index ''i'' o ''1'' a opakovane naňho voláme ''Heapify'' až do chvíle, kým neprídeme na začiatok poľa. Touto procedúrou preusporiadavame spodné jednoprvkové podhromady do 3-prvkových podhromád, tie do 7-prvkových podhromád ... až kým nedostaneme jednu N-prvkovú hromadu, kde ''N'' je počet prvkov v poli. Schematicky by sme to mohli napísať takto: |
<center><math> \text{pre } i \text{ z intervalu } \left \langle \left \lfloor \frac {\text{dĺžka}}{2} \right \rfloor - 1 \quad ; \quad 0 \right \rangle :\ \text{Heapify( pole[], dĺžka, i )}</math></center> | <center><math> \text{pre } i \text{ z intervalu } \left \langle \left \lfloor \frac {\text{dĺžka}}{2} \right \rfloor - 1 \quad ; \quad 0 \right \rangle :\ \text{Heapify( pole[], dĺžka, i )}</math></center> | ||
=====Zmazanie hromady===== | =====Zmazanie hromady===== | ||
− | Pri mazaní hromady vykonáme dve operácie. Ako prvé vymeníme prvok na vrchu hromady s koncovým prvkom hromady. Prvok čo je na konci poľa považujeme už za zmazaný, preto veľkosť hromady znížime o 1. Ďalej, aby sme splnili podmienky pre maximálnu binárnu hromadu, zavoláme funkciu Heapify na celú hromadu (vrch hromady je 0-tý prvok v poli). Tento proces opakujeme, | + | Pri mazaní hromady vykonáme dve operácie. Ako prvé vymeníme prvok na vrchu hromady s koncovým prvkom hromady. Prvok čo je na konci poľa považujeme už za zmazaný, preto veľkosť hromady znížime o 1. Ďalej, aby sme splnili podmienky pre maximálnu binárnu hromadu, zavoláme funkciu ''Heapify'' na celú hromadu (vrch hromady je 0-tý prvok v poli). Tento proces opakujeme, pokým v hromade neostanú žiadne prvky. |
Poznámka: Pri triediacom algoritme nemusíme mazať celú hromadu, stačí nám, keď v hromade ostane jeden prvok, pretože vtedy bude vstupné pole už utriedené. | Poznámka: Pri triediacom algoritme nemusíme mazať celú hromadu, stačí nám, keď v hromade ostane jeden prvok, pretože vtedy bude vstupné pole už utriedené. | ||
Riadok 124: | Riadok 124: | ||
<center><math>\text{pre } j \text{ z intervalu } \left \langle \text{dĺžka - 1} \quad ; \quad 0 \right ) : \ \ \text{Vymeň(pole[0], pole[$j$])} \ \ a \ \ \text{Heapify(pole[], dĺžka, 0)} </math></center> | <center><math>\text{pre } j \text{ z intervalu } \left \langle \text{dĺžka - 1} \quad ; \quad 0 \right ) : \ \ \text{Vymeň(pole[0], pole[$j$])} \ \ a \ \ \text{Heapify(pole[], dĺžka, 0)} </math></center> | ||
− | Z hľadiska implementácie môžeme vytvoriť rekurzívnu | + | Z hľadiska implementácie môžeme vytvoriť '''iteračnú''' aj '''rekurzívnu''' verziu, čo závisí len od toho, ako je implementovaná funkcia ''Heapify''. |
====Pseudokód==== | ====Pseudokód==== | ||
− | Nech funkcia Heap Sort má nasledovný prototyp: <code>HeapSort(pole[], dlzka)</code> | + | Nech funkcia ''Heap Sort'' má nasledovný prototyp: <code>HeapSort(pole[], dlzka)</code> |
:1. Nech: <code>i = dlzka / 2 - 1</code>, kde "/" predstavuje celočíslené delenie. | :1. Nech: <code>i = dlzka / 2 - 1</code>, kde "/" predstavuje celočíslené delenie. | ||
:2. Je <code>i >= 0</code> ? Ak áno, pokračuj krokom 2.1., inak skoč na krok 3. | :2. Je <code>i >= 0</code> ? Ak áno, pokračuj krokom 2.1., inak skoč na krok 3. | ||
− | :::2.1. Zavolaj funkciu <code>Heapify(pole[], dlzka, i)</code> | + | :::2.1. Zavolaj funkciu: <code>Heapify(pole[], dlzka, i)</code> |
− | :::2.2. Skoč na krok 2. | + | :::2.2. <code>i = i - 1</code> |
+ | :::2.3. Skoč na krok 2. | ||
:3. Nech: <code>j = dlzka - 1</code> | :3. Nech: <code>j = dlzka - 1</code> | ||
:4 Je <code> j > 0</code> ? Ak áno, pokračuj krokom 4.1, inak skonči. | :4 Je <code> j > 0</code> ? Ak áno, pokračuj krokom 4.1, inak skonči. | ||
:::4.1. Vymeň: <code>pole[0]</code> a <code>pole[j]</code> | :::4.1. Vymeň: <code>pole[0]</code> a <code>pole[j]</code> | ||
− | :::4.2. Zavolaj funkciu <code>Heapify(pole[], | + | :::4.2. Zavolaj funkciu: <code>Heapify(pole[], j, 0)</code> |
− | :::4.3. Skoč na krok 4. | + | :::4.3. <code>j = j - 1</code> |
+ | :::4.4. Skoč na krok 4. | ||
===Implementácia algoritmov Heapify a HeapSort v rôznych programovacích jazykoch=== | ===Implementácia algoritmov Heapify a HeapSort v rôznych programovacích jazykoch=== | ||
Riadok 231: | Riadok 233: | ||
int main() | int main() | ||
{ | { | ||
− | int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0 | + | int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1}; |
int dlzka = sizeof(pole) / sizeof(pole[0]); | int dlzka = sizeof(pole) / sizeof(pole[0]); | ||
Riadok 253: | Riadok 255: | ||
{ | { | ||
− | + | int lavy = 2 * index + 1; | |
− | + | int pravy = 2 * index + 2; | |
− | int max = index; | + | int max = index; |
+ | |||
+ | // určenie potomka s maximálnou hodnotou | ||
+ | if(lavy < dlzka && pole[lavy] >= pole[max]) | ||
+ | { | ||
+ | max = lavy; | ||
+ | } | ||
+ | |||
+ | if(pravy < dlzka && pole[pravy] > pole[max]) | ||
+ | { | ||
+ | max = pravy; | ||
+ | } | ||
+ | |||
+ | // porovnanie maximálneho potomka s rodičom | ||
+ | if(pole[max] > pole[index]) | ||
+ | { | ||
+ | Vymen(&pole[max], &pole[index]); | ||
+ | Heapify(pole, dlzka, max); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void HeapSort(int pole[], int dlzka) | ||
+ | { | ||
+ | // vytvor maximálnu hromadu (procedúra BuildMaxHeap) | ||
+ | for (int i = dlzka / 2 - 1 ; i >= 0; --i) | ||
+ | { | ||
+ | Heapify(pole, dlzka, i); | ||
+ | } | ||
+ | |||
+ | // zmaž všetky prvky z hromady | ||
+ | for (int j = dlzka - 1; j > 0; --j) | ||
+ | { | ||
+ | Vymen(&pole[0], &pole[j]); | ||
+ | Heapify(pole, j, 0); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | </tab> | ||
+ | |||
+ | <tab name="Iteračná C++" block> | ||
+ | <syntaxhighlight lang="C++"> | ||
+ | #include <iostream> | ||
+ | |||
+ | using std::cout; | ||
+ | using std::endl; | ||
+ | |||
+ | void Vymen(int &a, int &b); | ||
+ | void Heapify(int pole[], int dlzka, int index); | ||
+ | void HeapSort(int pole[], int dlzka); | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1}; | ||
+ | int dlzka = sizeof(pole) / sizeof(pole[0]); | ||
+ | |||
+ | HeapSort(pole, dlzka); | ||
+ | |||
+ | cout<<"Výsledné utriedené pole:"<<endl; | ||
+ | |||
+ | for(auto i: pole) | ||
+ | { | ||
+ | cout<<i<<" "; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void Vymen(int &a, int &b) | ||
+ | { | ||
+ | int tmp = a; | ||
+ | a = b; | ||
+ | b = tmp; | ||
+ | } | ||
+ | |||
+ | void Heapify(int pole[], int dlzka, int index) | ||
+ | { | ||
+ | int pravy, lavy, max; | ||
+ | |||
+ | while(2 * index + 1 < dlzka) | ||
+ | { | ||
+ | lavy = 2 * index + 1; | ||
+ | pravy = 2 * index + 2; | ||
// určenie potomka s maximálnou hodnotou | // určenie potomka s maximálnou hodnotou | ||
− | if( | + | if(pravy < dlzka && pole[pravy] > pole[lavy]) |
{ | { | ||
− | max = | + | max = pravy; |
} | } | ||
− | + | else | |
− | |||
{ | { | ||
− | max = | + | max = lavy; |
} | } | ||
Riadok 271: | Riadok 352: | ||
if(pole[max] > pole[index]) | if(pole[max] > pole[index]) | ||
{ | { | ||
− | Vymen( | + | |
− | + | Vymen(pole[max], pole[index]); | |
+ | index = max; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return; | ||
} | } | ||
+ | } | ||
} | } | ||
Riadok 287: | Riadok 374: | ||
for (int j = dlzka - 1; j > 0; --j) | for (int j = dlzka - 1; j > 0; --j) | ||
{ | { | ||
− | Vymen(&pole[0], &pole[j]); | + | Vymen(pole[0], pole[j]); |
+ | Heapify(pole, j, 0); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | </tab> | ||
+ | |||
+ | <tab name="Rekurzívna C++", block> | ||
+ | <syntaxhighlight lang="C++"> | ||
+ | #include <iostream> | ||
+ | |||
+ | using std::cout; | ||
+ | using std::endl; | ||
+ | |||
+ | void Vymen(int &a, int &b); | ||
+ | void Heapify(int pole[], int dlzka, int index); | ||
+ | void HeapSort(int pole[], int dlzka); | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1}; | ||
+ | int dlzka = sizeof(pole) / sizeof(pole[0]); | ||
+ | |||
+ | HeapSort(pole, dlzka); | ||
+ | |||
+ | cout<<"Výsledné utriedené pole:"<<endl; | ||
+ | |||
+ | for(auto i: pole) | ||
+ | { | ||
+ | cout<<i<<" "; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | void Vymen(int &a, int &b) | ||
+ | { | ||
+ | int tmp = a; | ||
+ | a = b; | ||
+ | b = tmp; | ||
+ | } | ||
+ | |||
+ | void Heapify(int pole[], int dlzka, int index) | ||
+ | { | ||
+ | |||
+ | int lavy = 2 * index + 1; | ||
+ | int pravy = 2 * index + 2; | ||
+ | int max = index; | ||
+ | |||
+ | // určenie potomka s maximálnou hodnotou | ||
+ | if(lavy < dlzka && pole[lavy] > pole[max]) | ||
+ | { | ||
+ | max = lavy; | ||
+ | } | ||
+ | |||
+ | if(pravy < dlzka && pole[pravy] > pole[max]) | ||
+ | { | ||
+ | max = pravy; | ||
+ | } | ||
+ | |||
+ | // porovnanie maximálneho potomka s rodičom | ||
+ | if(pole[max] > pole[index]) | ||
+ | { | ||
+ | Vymen(pole[max], pole[index]); | ||
+ | Heapify(pole, dlzka, max); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void HeapSort(int pole[], int dlzka) | ||
+ | { | ||
+ | // vytvor maximálnu hromadu (procedúra BuildMaxHeap) | ||
+ | for (int i = dlzka / 2 - 1 ; i >= 0; --i) | ||
+ | { | ||
+ | Heapify(pole, dlzka, i); | ||
+ | } | ||
+ | |||
+ | // zmaž všetky prvky z hromady | ||
+ | for (int j = dlzka - 1; j > 0; --j) | ||
+ | { | ||
+ | Vymen(pole[0], pole[j]); | ||
Heapify(pole, j, 0); | Heapify(pole, j, 0); | ||
} | } | ||
Riadok 294: | Riadok 460: | ||
</tab> | </tab> | ||
− | <tab name=" | + | |
+ | |||
+ | <tab name="Iteráčná Java" block> | ||
<syntaxhighlight lang="Java"> | <syntaxhighlight lang="Java"> | ||
class HeapSortIT { | class HeapSortIT { | ||
Riadok 375: | Riadok 543: | ||
</tab> | </tab> | ||
− | <tab name=" | + | <tab name="Rekurzívna Java" block> |
<syntaxhighlight lang="Java"> | <syntaxhighlight lang="Java"> | ||
class HeapSortRE { | class HeapSortRE { | ||
Riadok 451: | Riadok 619: | ||
</tab> | </tab> | ||
− | <tab name=" | + | <tab name="Iteračná Python3" block> |
<syntaxhighlight lang="Python3"> | <syntaxhighlight lang="Python3"> | ||
def heapify(pole, n): | def heapify(pole, n): | ||
Riadok 513: | Riadok 681: | ||
</tab> | </tab> | ||
− | <tab name=" | + | <tab name="Rekurzívna Python3" block> |
<syntaxhighlight lang="Python3"> | <syntaxhighlight lang="Python3"> | ||
def heapify(pole, n, i): | def heapify(pole, n, i): |
Aktuálna revízia z 18:50, 19. apríl 2021
Obsah
Heap Sort
Prehľad
Heap Sort je triediaci algoritmus, ktorý podobne ako Selection sort, rozeľuje pole na zotriedenú a nezotriedenú časť, pričom nezotriedená časť predstavuje dátovú štruktúru binárna hromada. Celé triedenie spočíva v tom, že si zo vstupného poľa vytvoríme binárnu hromadu a následne postupným vyberaním a mazaním všetkých jej prvkov toto pole utriedime.
Hromada, ktorú využíva algoritmus Heap Sort, musí spĺňať nasledovné podmienky (ak indexujeme pole od 0):
- 1. Vrchol hromady (koreň) je vždy prvý prvok v poli (v našom prípade prvok na 0-tej pozícii).
- 2. Pre ľubovoľný prvok (uzol), uložený na indexe [math]i[/math] z intervalu [math] \langle 0 \ ; \ \text{dĺžka} - 1 \rangle [/math], platia nasledovné rovnice:
- [math] \begin{align} \text{ľavý potomok} &= 2i + 1 && (1) \\ \text{pravý potomok} &= 2i + 2 && (2) \\ \text{rodič} &= \left \lfloor \frac{i - 1}{2} \right \rfloor \quad (\text {okrem} \ i = 0) && (3) \end{align} [/math]
- 3. Každý prvok (uzol) v hromade musí mať väčšiu, alebo rovnakú hodnotu ako jeho potomkovia (vlastnosť MAX HEAP - ak triedime pole vzostupne, v opačnom prípade by sme použili MIN HEAP).
Algoritmus Heapify

Heapify je kľúčovým podprogramom triediaceho algoritmu Heap Sort, vďaka ktorému vieme efektíve zabezpečiť procedúry: vytvorenie hromady z poľa a zmazanie hromady.
Princíp algoritmu Heapify spočíva v tom, že ak máme i-ty prvok v poli (v kompletnom binárnom strome), ktorého potomkovia tvoria dve samostatné podhromady, potom tieto dve podhromady preusporiadame do jednej hromady, pričom i-ty prvok bude jej vrcholom.
Vlastnosti algoritmu
- dátová štruktúra: hromada (reprezentovaná ako: pole)
- časová zložitosť: lineárna [math]O(n)[/math]
- priestorová zložitosť: konštantná [math]O(1)[/math] pri iteračnej verzii, [math]O(log(n))[/math] pri rekurzívnej verzii
Základné časti algoritmu
- Určenie potomka i-teho prvku s maximálnou hodnotou.
- Porovnanie hodnoty maximálneho potomka s hodnotou rodiča (i-tym prvkom).
- Ak je hodnota maximálneho potomka väčšia ako hodnota rodiča, tak výmena potomka a rodiča.
- Ak nastane výmena, skontrolovanie ovplyvneného potomka (podhromady).
Slovný opis algoritmu
Na vstupe prijmeme pole a index i, v ktorom chceme vytvoriť hromadu (Max Heap). Musí byť splnená podmienka, že oba potomkovia i-teho prvku tvoria dve samostatné podhromady. Najskôr skontrolujeme, či prvok na indexe i má nejakých potomkov (využijeme rovnice (1) a (2) z časti "Prehľad"). Ak nemá žiadnych potomkov, funkcia skončí, pretože i predstavuje vrchol jednoprvkovej hromady. Ak má práve jedného potomka, tento potomok je zároveň aj jeho maximálnym potomkom. Ak má práve dvoch potomkov, tak porovnáme ich hodnoty a vyberieme z nich maximálneho potomka. Následne skontrolujeme veľkosť maximálneho potomka a jeho rodiča (prvok na indexe i). Ak je rodič väčší, funkcia skončí, pretože želaná hromada už je utvorená. Ak nie, vymeníme rodiča a maximálneho potomka. Ak nastala výmena, musíme skontrolovať ovplyvnenú podhromadu, tj. zopakovať tento sled krokov pre podhromadu, ktorej vrchol bude v maximálnom potomkovi i-teho prvku.
Z hľadiska implementácie môžeme vytvoriť iteračnú aj rekurzívnu verziu.
Pseudokód
Nech funkcia Heapify má nasledovný prototyp: Heapify(pole[], dlzka, i)
- 1. Je
2 * i + 1 < dlzka
? Ak áno, pokračuj krokom 1.1., inak skonči.- 1.1. Nech:
lavy = 2 * i + 1
- 1.2. Nech:
pravy = 2 * i + 2
- 1.3. Je
pravy < dlzka
a zároveňpole[pravy] > pole[lavy]
?- Ak áno:
- 1.3.1. Nech:
max = pravy
- 1.3.1. Nech:
- Ak nie:
- 1.3.1. Nech:
max = lavy
- 1.3.1. Nech:
- Ak áno:
- 1.4. Je
pole[max] > pole[i]
?- Ak áno:
- 1.4.1. Vymeň:
pole[max]
apole[i]
- 1.4.2.
i = max
- 1.4.1. Vymeň:
- Ak nie:
- 1.4.1 Skonči.
- Ak áno:
- 1.5. Skoč na krok 1.
- 1.1. Nech:
Nech funkcia Heapify má nasledovný prototyp: Heapify(pole[], dlzka, i)
- 1. Nech:
lavy = 2 * i + 1
- 2. Nech:
pravy = 2 * i + 2
- 3. Nech:
max = i
- 4. Je
lavy < dlzka
a zároveňpole[lavy] > pole[max]
?- Ak áno:
- 4.1. Nech:
max = lavy
- 4.1. Nech:
- Ak nie:
- 4.1. Pokračuj krokom 5.
- Ak áno:
- 5. Je
pravy < dlzka
a zároveňpole[pravy] > pole[max]
?- Ak áno:
- 5.1. Nech:
max = pravy
- 5.1. Nech:
- Ak nie:
- 5.1. Pokračuj krokom 6.
- Ak áno:
- 6. Je
pole[max] > pole[i]
?- Ak áno:
- 6.1. Vymeň:
pole[i] a pole[max]
- 6.2. Rekurzívne zavolaj:
Heapify(pole[], dlzka, max)
- 6.1. Vymeň:
- Ak nie:
- 6.1. Skonči volanie.
- Ak áno:
Algoritmus Heap Sort
Heap Sort pri triedení vykonáva dve základné úlohy: Vytvorenie maximálnej binárnej hromady zo vstupného poľa a postupné mazanie jednotlivých prvkov z hromady. Pri oboch procedúrach využíva algoritmus Heapify.
Vlastnosti algoritmu
- vhodný pre dátové štruktúry: pole
- časová náročnosť: vždy linearitmická [math] O(n\log(n)) [/math], vďaka ktorej dokáže efektívne triediť veľmi veľké polia

- priestorová náročnosť: konštantná [math]O(1)[/math] pri iteračnej verzii, logaritmická [math]O(\log(n))[/math] pri rekurzívnej verzii.
- druh triedenia: triedenie výberom (komparačný algoritmus)
- stabilita triedenia: nestabilný
- miesto triedenia: vnútorné triedenie
Základné časti algoritmu
- Vytvorenie binárnej hromady z poľa.
- Zmazanie binárnej hromady.
Slovný opis
Vytvorenie hromady
Pri vytváraní hromady využijeme algoritmus Heapify, pričom hromadu vytvoríme spôsobom zospodu na vrch.
Najskôr si určíme rodiča posledného potomka. Využijeme rovnicu (3) z časti "Prehľad", ktorú si jemne upravíme:
Následne zavoláme Heapify na podhromadu s vrcholom na indexe i. Potom postupne zmenšujeme index i o 1 a opakovane naňho voláme Heapify až do chvíle, kým neprídeme na začiatok poľa. Touto procedúrou preusporiadavame spodné jednoprvkové podhromady do 3-prvkových podhromád, tie do 7-prvkových podhromád ... až kým nedostaneme jednu N-prvkovú hromadu, kde N je počet prvkov v poli. Schematicky by sme to mohli napísať takto:
Zmazanie hromady
Pri mazaní hromady vykonáme dve operácie. Ako prvé vymeníme prvok na vrchu hromady s koncovým prvkom hromady. Prvok čo je na konci poľa považujeme už za zmazaný, preto veľkosť hromady znížime o 1. Ďalej, aby sme splnili podmienky pre maximálnu binárnu hromadu, zavoláme funkciu Heapify na celú hromadu (vrch hromady je 0-tý prvok v poli). Tento proces opakujeme, pokým v hromade neostanú žiadne prvky.
Poznámka: Pri triediacom algoritme nemusíme mazať celú hromadu, stačí nám, keď v hromade ostane jeden prvok, pretože vtedy bude vstupné pole už utriedené.
Schematicky by sme to mohli zapísať takto:
Z hľadiska implementácie môžeme vytvoriť iteračnú aj rekurzívnu verziu, čo závisí len od toho, ako je implementovaná funkcia Heapify.
Pseudokód
Nech funkcia Heap Sort má nasledovný prototyp: HeapSort(pole[], dlzka)
- 1. Nech:
i = dlzka / 2 - 1
, kde "/" predstavuje celočíslené delenie. - 2. Je
i >= 0
? Ak áno, pokračuj krokom 2.1., inak skoč na krok 3.- 2.1. Zavolaj funkciu:
Heapify(pole[], dlzka, i)
- 2.2.
i = i - 1
- 2.3. Skoč na krok 2.
- 2.1. Zavolaj funkciu:
- 3. Nech:
j = dlzka - 1
- 4 Je
j > 0
? Ak áno, pokračuj krokom 4.1, inak skonči.- 4.1. Vymeň:
pole[0]
apole[j]
- 4.2. Zavolaj funkciu:
Heapify(pole[], j, 0)
- 4.3.
j = j - 1
- 4.4. Skoč na krok 4.
- 4.1. Vymeň:
Implementácia algoritmov Heapify a HeapSort v rôznych programovacích jazykoch
#include <stdio.h>
void Vymen(int *a, int *b);
void Heapify(int pole[], int dlzka, int index);
void HeapSort(int pole[], int dlzka);
int main()
{
int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1};
int dlzka = sizeof(pole) / sizeof(pole[0]);
HeapSort(pole, dlzka);
for (int i = 0; i < dlzka; ++i)
{
printf("%d ", pole[i]);
}
}
void Vymen(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void Heapify(int pole[], int dlzka, int index)
{
int pravy, lavy, max;
while(2 * index + 1 < dlzka)
{
lavy = 2 * index + 1;
pravy = 2 * index + 2;
// určenie potomka s maximálnou hodnotou
if(pravy < dlzka && pole[pravy] > pole[lavy])
{
max = pravy;
}
else
{
max = lavy;
}
// porovnanie maximálneho potomka s rodičom
if(pole[max] > pole[index])
{
Vymen(&pole[max], &pole[index]);
index = max;
}
else
{
return;
}
}
}
void HeapSort(int pole[], int dlzka)
{
// vytvor maximálnu hromadu (procedúra BuildMaxHeap)
for (int i = dlzka / 2 - 1 ; i >= 0; --i)
{
Heapify(pole, dlzka, i);
}
// zmaž všetky prvky z hromady
for (int j = dlzka - 1; j > 0; --j)
{
Vymen(&pole[0], &pole[j]);
Heapify(pole, j, 0);
}
}
#include <stdio.h>
void Vymen(int *a, int *b);
void Heapify(int pole[], int dlzka, int index);
void HeapSort(int pole[], int dlzka);
int main()
{
int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1};
int dlzka = sizeof(pole) / sizeof(pole[0]);
HeapSort(pole, dlzka);
for (int i = 0; i < dlzka; ++i)
{
printf("%d ", pole[i]);
}
}
void Vymen(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void Heapify(int pole[], int dlzka, int index)
{
int lavy = 2 * index + 1;
int pravy = 2 * index + 2;
int max = index;
// určenie potomka s maximálnou hodnotou
if(lavy < dlzka && pole[lavy] >= pole[max])
{
max = lavy;
}
if(pravy < dlzka && pole[pravy] > pole[max])
{
max = pravy;
}
// porovnanie maximálneho potomka s rodičom
if(pole[max] > pole[index])
{
Vymen(&pole[max], &pole[index]);
Heapify(pole, dlzka, max);
}
}
void HeapSort(int pole[], int dlzka)
{
// vytvor maximálnu hromadu (procedúra BuildMaxHeap)
for (int i = dlzka / 2 - 1 ; i >= 0; --i)
{
Heapify(pole, dlzka, i);
}
// zmaž všetky prvky z hromady
for (int j = dlzka - 1; j > 0; --j)
{
Vymen(&pole[0], &pole[j]);
Heapify(pole, j, 0);
}
}
#include <iostream>
using std::cout;
using std::endl;
void Vymen(int &a, int &b);
void Heapify(int pole[], int dlzka, int index);
void HeapSort(int pole[], int dlzka);
int main()
{
int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1};
int dlzka = sizeof(pole) / sizeof(pole[0]);
HeapSort(pole, dlzka);
cout<<"Výsledné utriedené pole:"<<endl;
for(auto i: pole)
{
cout<<i<<" ";
}
}
void Vymen(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void Heapify(int pole[], int dlzka, int index)
{
int pravy, lavy, max;
while(2 * index + 1 < dlzka)
{
lavy = 2 * index + 1;
pravy = 2 * index + 2;
// určenie potomka s maximálnou hodnotou
if(pravy < dlzka && pole[pravy] > pole[lavy])
{
max = pravy;
}
else
{
max = lavy;
}
// porovnanie maximálneho potomka s rodičom
if(pole[max] > pole[index])
{
Vymen(pole[max], pole[index]);
index = max;
}
else
{
return;
}
}
}
void HeapSort(int pole[], int dlzka)
{
// vytvor maximálnu hromadu (procedúra BuildMaxHeap)
for (int i = dlzka / 2 - 1 ; i >= 0; --i)
{
Heapify(pole, dlzka, i);
}
// zmaž všetky prvky z hromady
for (int j = dlzka - 1; j > 0; --j)
{
Vymen(pole[0], pole[j]);
Heapify(pole, j, 0);
}
}
#include <iostream>
using std::cout;
using std::endl;
void Vymen(int &a, int &b);
void Heapify(int pole[], int dlzka, int index);
void HeapSort(int pole[], int dlzka);
int main()
{
int pole[]= {10, 5, 2, 9, 8, 7, 1, 3, 4, 0, -1};
int dlzka = sizeof(pole) / sizeof(pole[0]);
HeapSort(pole, dlzka);
cout<<"Výsledné utriedené pole:"<<endl;
for(auto i: pole)
{
cout<<i<<" ";
}
}
void Vymen(int &a, int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void Heapify(int pole[], int dlzka, int index)
{
int lavy = 2 * index + 1;
int pravy = 2 * index + 2;
int max = index;
// určenie potomka s maximálnou hodnotou
if(lavy < dlzka && pole[lavy] > pole[max])
{
max = lavy;
}
if(pravy < dlzka && pole[pravy] > pole[max])
{
max = pravy;
}
// porovnanie maximálneho potomka s rodičom
if(pole[max] > pole[index])
{
Vymen(pole[max], pole[index]);
Heapify(pole, dlzka, max);
}
}
void HeapSort(int pole[], int dlzka)
{
// vytvor maximálnu hromadu (procedúra BuildMaxHeap)
for (int i = dlzka / 2 - 1 ; i >= 0; --i)
{
Heapify(pole, dlzka, i);
}
// zmaž všetky prvky z hromady
for (int j = dlzka - 1; j > 0; --j)
{
Vymen(pole[0], pole[j]);
Heapify(pole, j, 0);
}
}
class HeapSortIT {
void swap(int[] pole, int a, int b) {
int tmp = pole[a];
pole[a] = pole[b];
pole[b] = tmp;
}
void heapify(int[] pole, int n) {
for (int i = 1; i < n; i++) {
/* Ak je potomok väčší ako rodič */
if (pole[i] > pole[(i - 1) / 2]) {
int j = i;
/* Vymieňaj elementy (rodič, potomok), dokým je rodič menší ako potomok */
while (pole[j] > pole[(j - 1) / 2]) {
swap(pole, j, (j - 1) / 2);
j = (j - 1) / 2;
}
}
}
}
void sort(int[] pole) {
int n = pole.length;
heapify(pole, n);
for (int i = n - 1; i > 0; i--) {
int j = 0, index;
/* Vymeň prvý a posledný prvok */
swap(pole, 0, i);
do {
index = 2 * j + 1;
/* Ak je ľavý potomok menši ako pravý, presuň 'index' na pravého potomka */
if (index < i - 1 && pole[index] < pole[index + 1])
index++;
/* Ak je rodič menší ako potomok, tak ho vymeň s potomkom, ktorý má väčšiu hodnotu */
if (index < i && pole[j] < pole[index])
swap(pole, j, index);
j = index;
} while (index < i);
}
}
}
public class Main {
static void printArray(int[] pole) {
int n = pole.length;
for (int i : pole)
System.out.print(i + " ");
System.out.println();
}
public static void main(String[] args) {
int[] pole = {12, 11, 13, 5, 6, 7};
int n = pole.length;
System.out.println("Pole pred zoradenim: ");
printArray(pole);
HeapSortIT hs = new HeapSortIT();
hs.sort(pole);
System.out.println("Pole po zoradeni: ");
printArray(pole);
}
}
class HeapSortRE {
void swap(int[] pole, int a, int b) {
int tmp = pole[a];
pole[a] = pole[b];
pole[b] = tmp;
}
void heapify(int[] pole, int n, int i) {
int max = i; // rodič
int l = 2 * i + 1; // ľavý potomok
int p = 2 * i + 2; // pravý potomok
/* Ak je ľavý potomok väčší ako rodič */
if (l < n && pole[l] > pole[max])
max = l;
/* Ak je pravý potomok väčší ako rodič */
if (p < n && pole[p] > pole[max])
max = p;
/* Ak sa rodič v priebehu funkcie zmenil */
if (max != i) {
swap(pole, i, max);
heapify(pole, n, max);
}
}
public void sort(int[] pole) {
int n = pole.length;
/* Vytvorenie hromadu */
for (int i = n / 2 - 1; i >= 0 ; i--)
heapify(pole, n, i);
/* Extrahovanie jednotlivých elemetov z hromady */
for (int i = n - 1; i > 0; i--) {
/* Presuň aktuálneho rodiča na koniec */
swap(pole, 0, i);
/* Zavolanie heapify na zredukovanú hromadu */
heapify(pole, i, 0);
}
}
}
public class Main {
static void printArray(int[] pole) {
int n = pole.length;
for (int i : pole)
System.out.print(i + " ");
System.out.println();
}
public static void main(String[] args) {
int[] pole = {12, 11, 13, 5, 6, 7};
int n = pole.length;
System.out.println("Pole pred zoradenim: ");
printArray(pole);
HeapSortRE hs = new HeapSortRE();
hs.sort(pole);
System.out.println("Pole po zoradeni: ");
printArray(pole);
}
}
def heapify(pole, n):
for i in range(n):
# Ak je potomok väčší ako rodič
if pole[i] > pole[int((i - 1) / 2)]:
j = i
# Vymieňaj elementy (rodič, potomok), dokým je rodič menší ako potomok
while pole[j] > pole[int((j - 1) / 2)]:
pole[j], pole[int((j - 1) / 2)] = pole[int((j - 1) / 2)], pole[j] # swap
j = int((j - 1) / 2)
def sort(pole, n):
heapify(pole, n)
for i in range(n - 1, 0, -1):
# Vymeň prvý a posledný prvok
pole[0], pole[i] = pole[i], pole[0] # swap
j, index = 0, 0
while True:
index = 2 * j + 1
# Ak je ľavý potomok menši ako pravý, presuň 'index' na pravého potomka
if index < (i - 1) and pole[index] < pole[index + 1]:
index += 1
# Ak je rodič menší ako potomok, tak ho vymeň s potomkom, ktorý má väčšiu hodnotu
if index < i and pole[j] < pole[index]:
pole[j], pole[index] = pole[index], pole[j] # swap
j = index
if index >= i:
break
def printArray(pole, n):
for i in range(n):
print(pole[i], end=" ")
if __name__ == '__main__':
pole = [12, 11, 13, 5, 6, 7]
n = len(pole)
print("Zadane pole:")
printArray(pole, n)
sort(pole, n)
print("\nZoradene pole:")
printArray(pole, n)
def heapify(pole, n, i):
max = i # rodic
l = 2 * i + 1 # lavy potomok
p = 2 * i + 2 # pravy potomok
# Ak je ľavý potomok väčší ako rodič
if l < n and pole[max] < pole[l]:
max = l
# Ak je pravý potomok väčší ako rodič
if p < n and pole[max] < pole[p]:
max = p
# Ak sa rodič v priebehu funkcie zmenil
if max != i:
pole[i], pole[max] = pole[max], pole[i] # swap
heapify(pole, n, max)
def sort(pole):
n = len(pole)
# Vytvorenie hromady
for i in range(n // 2 - 1, -1, -1):
heapify(pole, n, i)
# Extrahovanie jednotlivých elementov z hromady
for i in range(n - 1, 0, -1):
pole[i], pole[0] = pole[0], pole[i] # swap
heapify(pole, i, 0)
def printArray(pole):
n = len(pole)
for i in range(n):
print(pole[i], end=" ")
if __name__ == '__main__':
pole = [12, 11, 13, 5, 6, 7]
print("Zadane pole:")
printArray(pole)
sort(pole)
print("\nZoradene pole:")
printArray(pole)
Selection Sort
Prehľad
Selection Sort je triediaci algoritmus, ktorý si rozdelí pole na dve časti: zotriedenú a nezotriedenú. Následne opakovane vyberá minimum v nezotriedenej časti (ak triedime vzostupne), ktoré umiestni na koniec utrienej časti.
Vlastnosti algoritmu
- vhodný pre dátové štruktúry: pole
- časová náročnosť: vždy kvadratická [math] O(n^2) [/math], čo znamená, že algoritmus je určený na triedenie veľmi malých polí (rádovo 10, 20 prvkov), vďaka minimálnej réžii a jednoduchej implementácii, avšak pre väčšie polia sa stáva veľmi neefektívny
- priestorová náročnosť: vždy konštantná [math]O(1)[/math]
- druh triedenia: triedenie výberom (komparačný algoritmus)
- stabilita triedenia: nestabilný
- miesto triedenia: vnútorné triedenie
Základné časti algoritmu
- Vonkajší cyklus: nastavenie hornej hranice utriedenej časti.
- Vnútorný cyklus: hľadanie minima ....
Slovný opis algoritmu
Pseudokód
Nech má funkcia Selection Sort nasledovný prototyp: SelectionSort(pole[], dlzka)
- 1. Nech:
min = pole[0]
- 2. Nech
i = 1
- 3. Je
i < dlzka
? Ak áno, pokračuj krokom 3.1., inak skonči.- 3.1. Nech:
j = i
- 3.2. Je
j < dlzka
? Ak áno, pokračuj krokom 3.2.1. , inak skoč na krok 3.3.- 3.2.1. Je
pole[j] < min
?- Ak áno:
- 3.2.1.1.
min = pole[j]
- 3.2.1.2. Skoč na krok 3.2.
- 3.2.1.1.
- Ak nie:
- 3.2.1.1. Skoč na krok 3.2.
- Ak áno:
- 3.2.1. Je
- 3.3. Vymeň:
pole[i]
apole[min]
- 3.4. Skoč na krok 3.2.
- 3.1. Nech:
Odkazy
Heap Sort:
https://en.wikipedia.org/wiki/Heapsort
https://www.geeksforgeeks.org/heap-sort/