4.3 Operace na Haldě
Binární minimová halda – Formalizace
Atributy haldy H
- H.root, který je aktuální kořen
- H.n, který udržuje aktuální počet prvků
- H.last, který udržuje ukazatel na aktuální poslední list (nejpravější list v poslední hladině), pokud existuje
Prvek haldy
- klíč
- ukazatel na otce
- ukazatele na své syny (jsou-li v haldě obsažené)
V následujícím textu předpokládáme, že výše uvedené proměnné máme a umíme je přepočítat v čase
Algoritmus 4.1 (HeapInsert)
Algoritmus HeapInsert
Vložení prvku do haldy HeapInsert(
Vstup
- Halda
. - klíč
přidávaného prvku
Výstup
- Halda
s přidaným prvkem s klíčem
Idea
- Vlastnost Tvar haldy dovoluje přidat okamžitě nový prvek na konec nejspodnější hladiny
- Pokud by již byla plná, založíme novou hladinu.
- Pokud je Haldové uspořádání mezi novým listem l a jeho otcem o v pořádku, můžeme skončit.
- Pokud ne, prohodíme
a . - Tím se ale může porušit vlastnost Haldového uspořádání mezi vrcholem
a otcem vrcholu . - Pokud pro ně Haldové uspořádání neplatí, opět jejich klíče prohodíme, jinak končíme.
- Toto opakujeme, nejdále však až do kořene.
Algoritmus
Časová složitost
Na každé hladině strávíme
Věta 4.3 (O koreknosti HeapInsert)
O koreknosti HeapInsert
Buď
HeapInsert(
Důkaz Věty 4.3
- Pokud H je prázdná, pak je výsledkem jednoprvková halda – hotovo.
- Jinak označme
výsledek volání HeapInsert( , ). má dle (3) tvar haldy.- Zbývá ověřit, že splňuje podmínku haldového uspořádání
- Po přidání hodnoty
do nového listu může existovat jen jedna hrana porušenou podmínkou. Tento problém pomocí funkce BubbleUp posouváme směrem ke kořeni. - Je třeba ověřit, že nemůžeme porušit podmínku haldového uspořádání mezi nějakým otcem
a jeho (případným) druhým synem na cestě z do kořene.- Pozorujeme, že hodnota
v se aplikováním BubbleUp nemohla zvýšit (může klesnout, případně zůstat stejná, pokud otec vrcholu měl stejnou hodnotu).
- Pozorujeme, že hodnota
Algoritmus 4.2 (HeapExtractMin)
Algoritmus HeapExtractMin
- Nalezení minima HeapFindMin(
) je triviální -> Vrátíme klíč kořene haldu v čase - HeapExtractMin(H) je komplikovanější: Odstranění kořene r = H.root stromu haldy by porušilo vlastnost tvar haldy.
- Nicméně je možné triviálně odstranit poslední list
, čili list nejvíc vpravo v poslední hladině.
Odstranění minima z haldy HeapExtractMin(
Vstup
- Halda
.
Výstup
- Halda
s odebraným prvkem s nejmenším klíčem
Idea
- Prohoď
a - Odstraň vrchol
a zmenši haldu o 1 prvek. - "Probublávej dolů" z kořene klíč
na jeho správné místo, aby opět platilo haldové uspořádání.
Algoritmus
Algoritmus HeapExtractMin(H): | |
---|---|
Časová složitost
Na každé hladině strávíme
Věta 4.4 (O koreknosti HeapExtractMin)
O koreknosti HeapExtractMin
Buď
HeapExtractMin(
Důkaz Věty 4.4
- Tvar haldy je opět zachován triviálně.
- Pokud je výsledkem prázdná či jednoprvková halda, máme hotovo
- Prohození z řádku 3 mohlo porušit haldové uspořádání (mezi hladinami 0 a 1).
- Opět prohazujeme s menším ze synů, čímž posunujeme porušení na dvojici následujících hladin.
- Toto může pokračovat jen do poslední hladiny.
K Zamyšlení
- Co se změní, když místo minimové haldy budeme pracovat s maximovou haldou a místo operací HeapExtractMin a HeapFindMin budeme tedy podporovat operace HeapExtractMax a HeapFindMax?
- Rozmyslete algoritmus operace HeapChangeKey, která dostane ukazatel na prvek uložený v haldě, ve kterém se má klíč změnit na zadanou hodnotu tak, aby výsledkem byla opět halda.
- Využitím operace HeapChangeKey lze definovat operaci, která umožňuje z haldy odstranit libovolný prvek zadaný ukazatelem. Popište její algoritmus.