Binomická hromada - Binomial heap - Wikipedia
v počítačová věda, a binomická hromada je datová struktura který funguje jako prioritní fronta ale také umožňuje sloučení párů hromád. Je to důležité jako implementace slučitelná hromada abstraktní datový typ (také zvaný tvárná hromada ), což je prioritní fronta podpora operace sloučení. Je implementován jako halda podobný a binární hromada ale pomocí speciální stromové struktury, která se liší od kompletní binární stromy používané binárními hromadami.[1] Binomické hromady byly vynalezeny v roce 1978 Jean Vuillemin.[1][2]
Binomická hromada
Binomická halda je implementována jako sada binomický stromy (porovnejte s a binární hromada, který má tvar singlu binární strom ), které jsou definovány rekurzivně takto:[1]
- Binomický strom řádu 0 je jeden uzel
- Binomický strom řádu má kořenový uzel, jehož děti jsou kořeny binomických stromů řádů , , ..., 2, 1, 0 (v tomto pořadí).
Binomický strom řádu má uzly a výška . Název pochází z tvaru: binomický strom řádu má uzly v hloubce , a binomický koeficient.Vzhledem ke své struktuře je to binomický strom řádu lze postavit ze dvou stromů řádu připojením jednoho z nich jako levého dítěte kořene druhého stromu. Tato funkce je pro spojit provoz binomické hromady, což je jeho hlavní výhoda oproti jiným konvenčním hromadám.[1][3]
Struktura binomické hromady
Binomická halda je implementována jako sada binomických stromů, které splňují vlastnosti binomické haldy:[1]
- Každý binomický strom v hromadě se řídí vlastnost minimum-heap: klíč uzlu je větší nebo roven klíči jeho rodiče.
- Může existovat pouze jeden jeden nebo nula binomické stromy pro každou objednávku, včetně nulové objednávky.
První vlastnost zajišťuje, že kořen každého binomického stromu obsahuje nejmenší klíč ve stromu. Z toho vyplývá, že nejmenší klíč v celé haldě je jedním z kořenů.[1]
Druhá vlastnost znamená, že binomická hromada s uzlů se skládá maximálně z binomické stromy, kde je binární logaritmus. Počet a pořadí těchto stromů je jednoznačně určeno počtem uzlů : existuje jeden binomický strom pro každý nenulový bit v souboru binární reprezentace čísla . Například desítkové číslo 13 je 1101 v binárním formátu, , a tedy binomická hromada s 13 uzly bude sestávat ze tří binomických stromů řádů 3, 2 a 0 (viz obrázek níže).[1][3]
Příklad binomické hromady obsahující 13 uzlů s odlišnými klíči.
Hromadu tvoří tři binomické stromy s řády 0, 2 a 3.
Počet různých způsobů, jak položky s odlišnými klávesami mohou být uspořádány do binomické hromady, která se rovná největšímu lichému děliteli . Pro tato čísla jsou
Pokud položky jsou vkládány do binomické hromady v rovnoměrně náhodném pořadí, každé z těchto uspořádání je stejně pravděpodobné.[3]
Implementace
Protože žádná operace nevyžaduje náhodný přístup ke kořenovým uzlům binomických stromů, mohou být kořeny binomických stromů uloženy v spojový seznam, seřazeno podle vzestupu pořadí stromu. Protože počet podřízených položek pro každý uzel je variabilní, nefunguje dobře, aby každý uzel měl samostatné odkazy na každé ze svých podřízených jednotek, jak by to bylo běžné v binární strom; místo toho je možné implementovat tento strom pomocí odkazů z každého uzlu na jeho dítě nejvyššího řádu ve stromu a na jeho sourozence dalšího menšího řádu než on. Tyto sourozenecké ukazatele lze interpretovat jako další ukazatele v propojeném seznamu podřízených položek každého uzlu, ale s opačným pořadím od propojeného seznamu kořenů: od největšího po nejmenší, spíše než naopak. Tato reprezentace umožňuje propojení dvou stromů stejného řádu, čímž se v konstantním čase vytvoří strom další větší objednávky.[1][3]
Spojit
Provoz společnosti slučování ve většině ostatních operací se jako podprogram používají dvě hromady. Základní podprogram v rámci tohoto postupu sloučí páry dvojčlenných stromů stejného řádu. Toho lze dosáhnout porovnáním klíčů v kořenech dvou stromů (nejmenší klíče v obou stromech). Z kořenového uzlu s větším klíčem se vytvoří podřízený kořenový uzel s menším klíčem, čímž se jeho pořadí zvýší o jednu:[1][3]
funkce mergeTree (p, q) -li p.root.key <= q.root.key vrátit se p.addSubTree (q) jiný vrátit se q.addSubTree (p)
Chcete-li sloučit dvě hromady obecněji, seznamy kořenů obou hromád se procházejí současně podobným způsobem jako u slučovací algoritmus, v pořadí od menších řádů stromů po větší řády. Když pouze jedna ze dvou hromad, které jsou sloučeny, obsahuje strom řádu , tento strom je přesunut do výstupní haldy. Když obě tyto hromady obsahují strom řádu , dva stromy jsou sloučeny do jednoho stromu řádu takže je splněna vlastnost minimum-heap. Později bude nutné sloučit tento strom s nějakým jiným stromem řádu v jedné ze dvou vstupních hromad. V průběhu algoritmu bude zkoumat maximálně tři stromy libovolného řádu, dva ze dvou hromad, které sloučíme, a jeden složený ze dvou menších stromů.[1][3]
funkce sloučit (p, q) zatímco ne (str. konec () a q.end ()) strom = mergeTree (p.currentTree (), q.currentTree ()) -li ne heap.currentTree (). empty () strom = mergeTree (strom, heap.currentTree ()) heap.addTree (strom) heap.next (); p.next (); q.next ()
Protože každý binomický strom v binomické hromadě odpovídá binárnímu vyjádření své velikosti trochu, existuje analogie mezi sloučením dvou hromad a binárním přidáním velikosti ze dvou hromad, zprava doleva. Kdykoli během sčítání dojde k přenosu, odpovídá to sloučení dvou binomických stromů během sloučení.[1][3]
Každý strom má maximálně objednávku a proto je doba provozu .[1][3]
Vložit
Vkládání nový prvek do haldy lze provést jednoduše vytvořením nové haldy obsahující pouze tento prvek a následným sloučením s původní haldou. Z důvodu sloučení trvá jediné vložení čas . To však lze zrychlit pomocí procedury sloučení, která zkratky sloučí poté, co dosáhne bodu, kdy pouze jedna ze sloučených hromad má stromy většího řádu. S tímto zrychlením napříč řadou po sobě jdoucích vložení, je celková doba vložení . Jiným způsobem, jak to vyjádřit, je to, že (po logaritmické režii pro první vložení do sekvence) každý po sobě vložit má amortizovaný čas z (tj. konstantní) na vložení.[1][3]
Varianta binomické hromady, zkosit binomickou hromadu, dosáhne konstantní doby vložení nejhoršího případu pomocí lesů, jejichž velikosti stromů jsou založeny na zkosit binární číselný systém spíše než v systému binárních čísel.[4]
Najděte minimum
Chcete-li najít minimální prvek hromady, najděte minimum mezi kořeny binomických stromů. To lze provést v čas, jako jsou právě kořeny stromů k prozkoumání.[1]
Použitím ukazatele na binomický strom, který obsahuje minimální prvek, lze čas pro tuto operaci zkrátit na . Ukazatel musí být aktualizován při provádění jakékoli jiné operace než hledání minima. To lze provést v čas na aktualizaci, aniž by se zvýšila celková asymptotická doba provozu jakékoli operace.[Citace je zapotřebí ]
Smazat minimum
Na odstranit minimální prvek z haldy nejprve najděte tento prvek, odeberte jej z kořene jeho binomického stromu a získejte seznam jeho podřízených podstromů (které jsou samy o sobě binomickými stromy různých řádů). Transformujte tento seznam podstromů na samostatnou binomickou hromadu jejich uspořádáním od nejmenšího po největší. Poté sloučte tuto hromadu s původní hromadou. Protože každý kořen má nanejvýš děti, vytvoření této nové hromady nějakou dobu trvá . Sloučení hromád vyžaduje čas , takže celá minimální operace mazání nějakou dobu trvá .[1]
funkce deleteMin (halda) min = heap.trees (). first () pro každého proud v heap.trees () -li current.rootpak min = aktuální pro každého strom v min.subTrees () tmp.addTree (strom) halda. odebratTree (min) sloučit (halda, tmp)
Snížit klíč
Po klesající klíč elementu, může se stát menším než klíč jeho rodiče, což porušuje vlastnost minimum-heap. Pokud tomu tak je, vyměňte prvek s jeho nadřazeným prvkem a případně také s jeho prarodičem atd., Dokud již nebude porušena vlastnost minimum-heap. Každý binomický strom má maximálně výšku , takže to trvá čas.[1] Tato operace však vyžaduje, aby reprezentace stromu obsahovala ukazatele z každého uzlu na jeho rodiče ve stromu, což trochu komplikuje implementaci dalších operací.[3]
Vymazat
Na vymazat prvek z haldy, snižte jeho klíč na záporné nekonečno (nebo ekvivalentně na nějakou hodnotu nižší než jakýkoli prvek v haldě) a poté v haldě odstraňte minimum.[1]
Aplikace
Viz také
- Slabá hromada, kombinace binární haldy a binomické haldy datových struktur
Reference
- ^ A b C d E F G h i j k l m n Ó str q Cormen, Thomas H.; Leiserson, Charles E.; Rivest, Ronald L.; Stein, Clifford (2001) [1990]. „Kapitola 19: Binomické hromady“. Úvod do algoritmů (2. vyd.). MIT Press a McGraw-Hill. 455–475. ISBN 0-262-03293-7.
- ^ Vuillemin, Jean (1. dubna 1978). Msgstr "Datová struktura pro manipulaci s prioritními frontami". Komunikace ACM. 21 (4): 309–315. doi:10.1145/359460.359478.
- ^ A b C d E F G h i j Brown, Mark R. (1978). "Implementace a analýza algoritmů binomické fronty". SIAM Journal on Computing. 7 (3): 298–319. doi:10.1137/0207026. PAN 0483830.
- ^ Brodal, Gerth Stølting; Okasaki, Chris (listopad 1996), „Optimální čistě funkční prioritní fronty“, Journal of Functional Programming, 6 (6): 839–857, doi:10.1017 / s095679680000201x
externí odkazy
- Dvě C implementace binomické hromady (obecný a jeden optimalizovaný pro celočíselné klíče)
- Haskell implementace binomické haldy
- Běžná implementace binomické haldy Lisp