D-regulární halda je n-ární úplný strom (zaplňovaný zleva doprava), ve kterém platí, že každý předek má nižší hodnotu (prioritu) než všichni jeho potomci. Tento typ uspořádání haldy se nazývá min heap, v případě opačného uspořádání hovoříme o max heap. Speciálním případem d-regulární haldy pro je binární halda. D-regulární halda funguje díky svým vlastnostem jako prioritní fronta.
Implementace
Za předpokladu, že implemetujeme haldu pomocí pole indexovaného od 0, tak nalezneme předka prvku na indexu . Potomky tohoto prvku nalezneme na indexech . Je vhodné, aby bylo mocninou čísla 2, protože pak můžeme nahradit operace násobení a dělení bitovými posuvy.
Kód
/** * D-regularni halda (d-ary heap) * Implementovana jako min-heap * @author Pavel Micka */ public class DAryHeap<ENTITY extends Comparable> { private final static int EXPAND_RATIO = 2; //kolikrat bude pole hodnot zvetseno pri expanzi private final static double COLLAPSE_RATIO = 0.25; //pomer pri nemz bude pole hodnot kontrahovano private Object[] array; private int d; //parametr d (arita) private int size; //velikost haldy private int initialSize; /** * Konstruktor * @param arraySize inicialni kapacita haldy */ public DAryHeap(int initialSize, int d) { if (d < 2) { throw new IllegalArgumentException("D must be at least 2."); } this.d = d; this.array = new Object[initialSize]; this.initialSize = initialSize; this.size = 0; } /** * Vlozi prvek do haldy * Slozitost: O(log(n)) * @param i prvek, ktery bude vlozen */ public void insert(ENTITY i) { if (array.length == size) { expand(); } size++; int index = size - 1; int parentIndex = getParentIndex(index); while (index != 0 && i.compareTo(array[parentIndex]) < 0) { //pokud je prvek mensi nez jeho otec array[index] = array[parentIndex]; //posun otce o uroven nize index = parentIndex; //opakuj proceduru na dalsi urovni parentIndex = getParentIndex(index); } array[index] = i; //umisti prvek na prislusnou pozici } /** * Vrati a odstrani prvek na vrchu haldy * Slozitost: O(log(n)) * @return prvek na vrchu haldy */ public ENTITY returnTop() { if (size == 0) { throw new IllegalStateException("Heap is empty"); } ENTITY tmp = (ENTITY) array[0]; array[0] = array[size - 1]; size--; if (size < array.length * COLLAPSE_RATIO && array.length / EXPAND_RATIO > initialSize) { collapse(); } repairTop(0); return tmp; } /** * Slouci danou haldu do teto haldy * Slozitost: O(n) * @param heap halda, jez bude sloucena do teto haldy */ public void merge(DAryHeap<ENTITY> heap) { Object[] newArray = new Object[array.length + heap.array.length]; System.arraycopy(array, 0, newArray, 0, size); System.arraycopy(heap.array, 0, newArray, size, heap.size); size = size + heap.size; array = newArray; //build heap for (int i = newArray.length / d; i >= 0; i--) { repairTop(i); } } /** * Vrat index rodicovskeho uzlu stromu * @param index index prvku, pro nejz bude vyhledan rodic * @return index rodicovskeho uzlu stromu */ private int getParentIndex(int index) { return (index - 1) / d; } /** * Umisti vrchol haldy na spravne misto v halde (tj. opravi vlasnost haldy usporadani) * @param topIndex index vrcholu haldy */ private void repairTop(int topIndex) { Comparable tmp = (Comparable) array[topIndex]; int succ = findSuccessor(topIndex * d + 1, topIndex * d + d); while (succ < size && tmp.compareTo(array[succ]) > 0) { array[topIndex] = array[succ]; topIndex = succ; succ = findSuccessor(succ * d + 1, succ * d + d); } array[topIndex] = tmp; } /** * Vrati index potomka s nejnizsi hodnotou * @param from index prvniho potomka * @param to index posledniho potomka * @return index index potomka s nejnizsi hodnotou */ private int findSuccessor(int from, int to) { int succ = from; for (int i = from + 1; i <= to && i < size; i++) { if (((Comparable) array[succ]).compareTo((Comparable) array[i]) > 0) { succ = i; } } return succ; } /** * Expanduje pole hodnot */ private void expand() { array = Arrays.copyOf(array, array.length * EXPAND_RATIO); } /** * Kontraguje pole hodnot */ private void collapse() { array = Arrays.copyOf(array, array.length / EXPAND_RATIO); } @Override public String toString() { StringBuilder builder = new StringBuilder(); for (int i = 0; i < size; i++) { builder.append(array[i]).append(" "); } return builder.toString(); } }