Modul heapq je implementací minimální haldy, tj. haldy, kde rodič je menší než všichni jeho potomci (a tudíž kořenem je nejmenší prvek).
Pythoní halda se na první pohled úmyslně tváří jako pythoní seznam – prvky se indexují od 0 a seřazení haldy pomocí metody sort() nezmění její haldovské vlastnosti.
PS: Jméno modulu pochází ze spojení heap queue algorithm – haldy se totiž v praxi velmi často používají pro implementaci prioritních front.
Vzhledem k tomu, že halda je z praktických důvodů reprezentována jako seznam, jehož jednotlivé prvky mají vyhovující vlastnosti, pracuje se s modulem heapq trošku netradičně – haldy jsou prostě seznamy, které se předávají metodám tohoto modulu, a tyto metody se starají o to, aby po provedené operaci byl vložený seznam stále haldou. Symbolicky:
Základním způsobem, jak vytvořit novou haldu, je vyjít od prázdného seznamu a postupně ho plnit prvek po prvku metodou heappush(HALDA, PRVEK)
:
Druhou možností zavedení haldy je vzít seznam prvků a metodou heapify(SEZNAM)
ho převést na haldu:
Nejmenší prvek haldy se v pythoní implementaci schovává na nultém indexu příslušného haldového seznamu. Nemůžete ho samozřejmě jen tak vyříznout pryč, protože to, co by zůstalo, by s velkou pravděpodobností už nebyla halda. Od toho je zde funkce heappop(HALDA)
:
IndexError
.
Často je potřeba aplikovat sekvence operací pop a push. Modul heapq poskytuje dvě další operace, které jsou pro dvě dvojce uvedených operací v příslušném pořadí rychlejší, než samostatné provedení obou operací po sobě:
heappushpop(HALDA, PRVEK)
nahrazuje dvoukrok push-pop;
heapreplace(HALDA, PRVEK)
nahrazuje dvoukrok pop-push.
Příklad:
Přímočará implementace algoritmu heapsort pomocí modulu heapq – nejdřív hodnoty jednu po druhé vložíme do haldy pomocí operace heappush(), odkud je pak postupně od nejmenšího operací heappop() vytaháme:
Zajímavostí modulu heapq je to, že používaná datová struktura je seznam a jak každý ví, prvky seznamu může být cokoliv. Jediná podmínka, aby to všechno dobře fungovalo, jest, že typy prvků musí být srovnatelné (a nejlépe i úplně stejné). Příklad podle dokumentace:
Datová struktura haldy je dosti používaná, proto asi nepřekvapí, že modul heapq obsahuje kromě výše uvedených haldových metod i několik dalších používajících haldu ke konkrétním úkolům:
Metoda heapq.merge(*ITERABLES)
očekává na vstupu libovolné množství již seřazených iterovatelných struktur, které dokáže slét dohromady ve správném pořadí. Její výhodou je, že výsledek poskytuje jako iterátor, takže by mohla dobře fungovat pro velká vstupní data:
sorted(itertools.chain(xs1, xs2, xs3))
.
Máte-li na vstupu iterovatelnou strukturu, můžete se jí ptát na nejmenší a největší prvky. Podle počtu požadovaných vrácených prvků lze rozlišit následující tři případy:
Malý příklad pro haldovské metody: