Heapsort časová zložitosť

Heapsort Casova Zlozitost



Heap Sort, napísaný ako Heapsort, je druh triediaceho algoritmu. Zoberie zoznam, ktorý je čiastočne usporiadaný, a vytvorí z neho zoradený zoznam. Triedenie môže byť vzostupné alebo zostupné. V tomto článku je triedenie vzostupné. Všimnite si, že heapsort netriedi neúplne neutriedený zoznam. Zoradí čiastočne usporiadaný (zoradený) zoznam. Tento čiastočne usporiadaný zoznam je hromada. V tomto článku je uvažovaná halda minimálna (vzostupná) halda.

Halda sa označuje ako „čiastočne usporiadaná“ a nie „čiastočne vytriedená“. Slovo „triediť“ znamená úplné zoradenie (kompletné zoradenie). Hromada nie je čiastočne usporiadaná svojvoľne. Halda je čiastočne usporiadaná podľa kritéria (vzoru), ako je uvedené nižšie.

Heapsort teda pozostáva z dvoch etáp: zostavenie haldy a extrakcia usporiadaného prvku z hornej časti haldy. V druhej etape sa po každej ťažbe halda znovu postaví. Každá prestavba je rýchlejšia ako pôvodný stavebný proces, pretože prestavba sa vykonáva z predchádzajúcej stavby, kde bol odstránený jeden prvok. A s tým, heapsort triedi úplne netriedený zoznam.







Cieľom tohto článku je stručne vysvetliť heapsort a následne vytvoriť jeho časovú zložitosť (pozri význam časovej zložitosti nižšie). Ku koncu sa kódovanie vykonáva v C++.



Minimálna halda

Halda môže byť minimálna alebo maximálna halda. Maximálna halda je taká, kde prvý prvok je najvyšší prvok a celý strom alebo zodpovedajúci zoznam je čiastočne zoradený v zostupnom poradí. Minimálna halda je taká, kde prvý prvok predstavuje najmenší prvok a celý zoznam je čiastočne usporiadaný vo vzostupnom poradí. V tomto článku sa berie do úvahy len minimálna hromada. Poznámka: v téme halda sa prvok nazýva aj uzol.



Halda je úplný binárny strom. Binárny strom môže byť vyjadrený ako pole (zoznam); čítať zhora nadol a zľava doprava. Vlastnosť haldy pre mini-hromadu je, že nadradený uzol je menší alebo rovný každému z jeho dvoch potomkov. Príkladom neusporiadaného zoznamu je:





9 19 24 5 3 jedenásť 14 22 7 6 17 pätnásť nulový nulový nulový
0 1 dva 3 4 5 6 7 8 9 10 jedenásť 12 13 14

Prvý riadok tejto tabuľky sú prvky poľa. V druhom riadku sú indexy založené na nule. Tento zoznam prvkov možno vyjadriť ako strom. Boli pridané nulové prvky, aby sa vytvoril úplný binárny strom. Presne povedané, nulové prvky nie sú súčasťou zoznamu (stromu). Tento zoznam nemá poradie, takže to ešte nie je hromada. Stane sa haldou, keď bude mať čiastočné usporiadanie podľa vlastnosti haldy.

Vzťah medzi uzlami a indexmi

Pamätajte si, že halda je úplný binárny strom predtým, ako budete mať konfiguráciu haldy (vlastnosť haldy). Predchádzajúci zoznam ešte nie je halda, pretože prvky sa neriadia vlastnosťou halda. Stane sa haldou po preusporiadaní prvkov do čiastočného poradia podľa vlastnosti min-heap. Čiastočné zoradenie možno považovať za čiastočné zoradenie (hoci slovo „zoradiť“ znamená úplné zoradenie).



Či už je binárny strom hromadou alebo nie, každý rodič má dve deti, okrem listových (posledných) uzlov. Medzi indexmi medzi každým rodičom a jeho deťmi existuje matematický vzťah. Je to nasledovné: Ak je rodič na indexe i, potom ľavý potomok je na indexe:

dva * i + 1

a správne dieťa je na indexe:

dva * i + dva

Toto je pre indexovanie založené na nule. A tak rodič na indexe 0 má svojho ľavého potomka na indexe 2×0+1=1 a jeho pravého potomka na 2×0+2=2. Rodič na indexe 1 má svojho ľavého potomka na indexe 2×1+1=3 a pravého potomka na indexe 2×1+2=4; a tak ďalej.

Podľa vlastnosti min-heap je rodič v i je menší alebo rovný ľavému potomkovi v 2i+1 a menší alebo rovný pravému potomkovi v 2i+2.

Hromada

Hromadenie znamená budovanie hromady. Znamená to preusporiadať prvky zoznamu (alebo zodpovedajúceho stromu) tak, aby vyhovovali vlastnosti haldy. Na konci procesu hromadenia je zoznam alebo strom hromada.

Ak je predchádzajúci nezoradený zoznam nahromadený, stane sa:

3 5 jedenásť 7 6 pätnásť 14 22 9 19 17 24 nulový nulový nulový
0 1 dva 3 4 5 6 7 8 9 10 jedenásť 12 13 14

Poznámka: v zozname je 12 prvkov a nie 15. V druhom riadku sú indexy. V procese budovania haldy bolo potrebné skontrolovať prvky a niektoré vymeniť.

Všimnite si, že najmenší a prvý prvok je 3. Ostatné prvky nasledujú vzostupne, ale zvlnene. Ak sú ľavé a pravé podriadené položky na pozíciách 2i+1 a 2i+2 väčšie alebo rovnaké ako rodič na i, potom ide o minimálnu hromadu. Toto nie je úplné zoradenie alebo triedenie. Toto je čiastočné zoradenie podľa vlastnosti haldy. Odtiaľ začína ďalšia fáza triedenia haldy.

Heapify časová zložitosť

Časová zložitosť je relatívna doba chodu nejakého kódu. Môže sa považovať za počet hlavných operácií, ktoré má tento kód dokončiť. Existujú rôzne algoritmy na vytváranie haldy. Najefektívnejšie a najrýchlejšie priebežne delia zoznam dvomi, kontrolujú prvky zdola a potom vymieňajú prvky. Nech N je počet praktických prvkov v zozname. S týmto algoritmom je maximálny počet hlavných operácií (swapovanie) N. Časová zložitosť heapifikácia bola predtým daná ako:

O ( n )

Kde n je N a je maximálny možný počet hlavných operácií. Tento zápis sa nazýva Big-O zápis. Začína sa písmenom O veľkým písmenom, za ktorým nasledujú zátvorky. V zátvorkách je výraz pre najvyšší možný počet operácií.

Pamätajte: sčítanie sa môže stať násobením, ak sa stále opakuje to isté, čo sa pridáva.

Heapsort ilustrácie

Predchádzajúci neutriedený zoznam sa použije na ilustráciu zoradenia. Uvedený zoznam je:

9 19 24 5 3 jedenásť 14 22 7 6 17 pätnásť

Minimálna hromada vytvorená zo zoznamu je:

3 5 jedenásť 7 6 pätnásť 14 22 9 19 17 24

Prvou fázou pri triedení haldy je výroba haldy, ktorá bola vyrobená. Toto je čiastočne usporiadaný zoznam. Nie je to zoradený (úplne zoradený) zoznam.

Druhá fáza pozostáva z odstránenia najmenšieho prvku, ktorý je prvým prvkom, z haldy, opätovného nahromadenia zostávajúcej haldy a odstránenia najmenšieho počtu prvkov vo výsledkoch. Najmenší prvok je vždy prvým prvkom v znovu nahromadenej halde. Prvky sa neodstraňujú a nevyhadzujú. Môžu byť odoslané do iného poľa v poradí, v akom boli odstránené.

Nakoniec by nové pole malo všetky prvky zoradené (úplne) vo vzostupnom poradí; a už nie len čiastočne objednané.

V druhej fáze je potrebné najskôr odstrániť 3 a umiestniť ich do nového poľa. Výsledky sú:

3

a

5 jedenásť 7 6 pätnásť 14 22 9 19 17 24

Zostávajúce prvky sa musia nahromadiť pred extrahovaním prvého prvku. Hromada zostávajúcich prvkov sa môže stať:

5 6 7 9 pätnásť 14 22 jedenásť 19 17 24

Extrahovaním 5 a pridaním do nového zoznamu (pola) získate výsledky:

3 5

a

6 7 9 pätnásť 14 22 jedenásť 19 17 24

Nahromadenie zostávajúcej sady by poskytlo:

6 7 9 pätnásť 14 22 jedenásť 19 17 24

Extrahovaním 6 a pridaním do nového zoznamu (pola) získate výsledky:

3 5 6

a

7 9 pätnásť 14 22 jedenásť 19 17 24

Nahromadenie zostávajúcej sady by poskytlo:

7 9 jedenásť 14 22 pätnásť 19 17 24

Extrahovaním 7 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7

a

9 jedenásť 14 22 pätnásť 19 17 24

Nahromadením zostávajúcej sady získate:

9 jedenásť 14 22 pätnásť 19 17 24

Extrahovaním 9 a pridaním do nového zoznamu získate výsledky:

3 5 6 7 9

a

jedenásť 14 22 pätnásť 19 17 24

Nahromadením zostávajúcej sady získate:

jedenásť 14 17 pätnásť 19 22 24

Extrahovaním 11 a jej pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť

a

14 17 pätnásť 19 22 24

Nahromadenie zostávajúcej sady by poskytlo:

14 17 pätnásť 19 22 24

Extrahovaním 14 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14

a

17 pätnásť 19 22 24

Nahromadenie zostávajúcej sady by poskytlo:

pätnásť 17 19 22 24

Extrahovaním 15 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14 pätnásť

a

17 19 22 24

Nahromadenie zostávajúcej sady by poskytlo:

17 19 22 24

Extrahovaním 17 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14 pätnásť 17

a

19 22 24

Nahromadenie zostávajúcej sady by poskytlo:

19 22 24

Extrahovaním 19 a jej pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14 pätnásť 17 19

a

22 24

Nahromadením zostávajúcej sady získate:

22 24

Extrahovaním 22 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14 pätnásť 17 19 22

a

24

Nahromadením zostávajúcej sady získate:

24

Extrahovaním 24 a jeho pridaním do nového zoznamu získate výsledky:

3 5 6 7 9 jedenásť 14 pätnásť 17 19 22 24

a

- - -

Pole haldy je teraz prázdne. Všetky prvky, ktoré mal na začiatku, sú teraz v novom poli (zozname) a sú zoradené.

Heapsort algoritmus

Aj keď sa čitateľ mohol v učebniciach dočítať, že heapsort pozostáva z dvoch etáp, heapsort môže byť stále vnímaný ako pozostávajúci z jednej fázy, ktorá sa iteratívne zmenšuje z daného poľa. Algoritmus triedenia pomocou heapsortu je teda nasledujúci:

  • Rozšírte netriedený zoznam.
  • Extrahujte prvý prvok haldy a vložte ho ako prvý prvok nového zoznamu.
  • Rozšírte zostávajúci zoznam.
  • Extrahujte prvý prvok novej haldy a vložte ho ako ďalší prvok nového zoznamu.
  • Opakujte predchádzajúce kroky v poradí, kým zoznam haldy nebude prázdny. Nakoniec je nový zoznam zoradený.

Správna časová zložitosť Heapsort

Jednostupňový prístup sa používa na určenie časovej zložitosti pre heapsort. Predpokladajme, že existuje 8 nezoradených prvkov na triedenie.

Možný maximálny počet operácií na nahromadenie 8 prvky je 8 .
The možný maximálny počet operácií na nahromadenie zostávajúceho 7 prvky je 7 .
The možný maximálny počet operácií na nahromadenie zostávajúceho 6 prvky je 6 .
The možný maximálny počet operácií na nahromadenie zostávajúceho 5 prvky je 5 .
The možný maximálny počet operácií na nahromadenie zostávajúceho 4 prvky je 4 .
The možný maximálny počet operácií na nahromadenie zostávajúceho 3 prvky je 3 .
The možný maximálny počet operácií na nahromadenie zostávajúceho dva prvky je dva .
The možný maximálny počet operácií na nahromadenie zostávajúceho 1 prvkom je 1 .

Maximálny možný počet operácií je:

8 + 7 + 6 + 5 + 4 + 3 + dva + 1 = 36

Priemer týchto počtov operácií je:

36 / 8 = 4.5

Všimnite si, že posledné štyri kôpky na predchádzajúcej ilustrácii sa po odstránení prvého prvku nezmenili. Niektoré z predchádzajúcich kôp sa tiež nezmenili, keď bol odstránený prvý prvok. S tým je lepší priemerný počet hlavných operácií (swapov) 3 a nie 4,5. Takže lepší celkový priemerný počet hlavných operácií je:

24 = 8 X 3
=> 24 = 8 X log < sub > dva < / sub > 8

od log dva 8 = 3.

Vo všeobecnosti je priemerná časová zložitosť prípadu pre heapsort:

O ( n. log2n )

Kde bodka znamená násobenie a n je N, celkový počet prvkov v zozname (oboch zoznamoch).

Všimnite si, že operácia extrakcie prvého prvku bola ignorovaná. Pri téme časovej zložitosti sa ignorujú operácie, ktoré trvajú relatívne krátky čas.

Kódovanie v C++

V knižnici algoritmov C++ existuje funkcia make_heap(). Syntax je:

šablóna < trieda RandomAccessIterator, trieda Porovnaj >
constexpr neplatné vytvoriť_hromadu ( RandomAccessIterator prvý, RandomAccessIterator posledný, Porovnať komp ) ;

Ako svoj prvý argument berie iterátor ukazujúci na prvý prvok vektora a potom ako posledný argument iterátor ukazujúci tesne za koniec vektora. Pre predchádzajúci neutriedený zoznam by sa na získanie minimálnej haldy použila syntax nasledovne:

vektor < int > vtr = { 9 , 19 , 24 , 5 , 3 , jedenásť , 14 , 22 , 7 , 6 , 17 , pätnásť } ;
vektor < int > :: iterátor iterB = vtr. začať ( ) ;
vektor < int > :: iterátor iterE = vtr. koniec ( ) ;
vytvoriť_hromadu ( iterB, iterE, väčší < int > ( ) ) ;

Tento kód zmení vektorový obsah na minimálnu konfiguráciu haldy. V nasledujúcich vektoroch C++ sa namiesto dvoch polí použijú dva vektory.

Ak chcete skopírovať a vrátiť prvý prvok vektora, použite syntax vektora:

constexpr referenčná predná strana ( ) ;

Ak chcete odstrániť prvý prvok vektora a zahodiť ho, použite syntax vektora:

constexpr iterátor vymazať ( pozícia const_iterator )

Ak chcete pridať prvok na zadnú stranu vektora (ďalší prvok), použite syntax vektora:

constexpr neplatné push_back ( konšt T & X ) ;

Začiatok programu je:

#include
#include
#include
použitím menný priestor std ;

Obsahuje algoritmus a vektorové knižnice. Ďalej v programe je funkcia heapsort(), čo je:

neplatné hepsort ( vektor < int > & oldV, vektor < int > & novýV ) {
ak ( starýV. veľkosť ( ) > 0 ) {
vektor < int > :: iterátor iterB = starýV. začať ( ) ;
vektor < int > :: iterátor iterE = starýV. koniec ( ) ;
vytvoriť_hromadu ( iterB, iterE, väčší < int > ( ) ) ;

int Ďalšie = starýV. vpredu ( ) ;
starýV. vymazať ( iterB ) ;
novýV. push_back ( Ďalšie ) ;
hepsort ( staréV, novéV ) ;
}
}

Ide o rekurzívnu funkciu. Používa funkciu make_heap() knižnice algoritmov C++. Druhý segment kódu v definícii funkcie extrahuje prvý prvok zo starého vektora po vytvorení haldy a pridá ho ako ďalší prvok pre nový vektor. Všimnite si, že v definícii funkcie sú parametre vektora referencie, zatiaľ čo funkcia sa volá s identifikátormi (názvami).

Na to je vhodná hlavná funkcia C++:

int hlavné ( int argc, char ** argv )
{
vektor < int > starýV = { 9 , 19 , 24 , 5 , 3 , jedenásť , 14 , 22 , 7 , 6 , 17 , pätnásť } ;
vektor < int > novýV ;
hepsort ( staréV, novéV ) ;

pre ( int i = 0 ; i < novýV. veľkosť ( ) ; i ++ ) {
cout << novýV [ i ] << ' ' ;
}
cout << endl ;

vrátiť 0 ;
}

Výstupom je:

3 5 6 7 9 jedenásť 14 pätnásť 17 19 22 24

triedené (úplne).

Záver

Článok podrobne rozoberá povahu a funkciu Heap Sort bežne známeho ako Heapsort ako triediaci algoritmus. Heapify Time Complexity, Heapsort ilustrácie a Heapsort ako algoritmus boli pokryté a podporené príkladmi. Priemerná časová zložitosť dobre napísaného heapsortového programu je O(nlog(n))