what is heap data structure java
Tento výukový program vysvětluje, co je datová struktura Java Heap a související pojmy jako Min Heap, Max Heap, Heap Sort, Stack vs Heap, s příklady:
Hromada je speciální datová struktura v Javě. Halda je stromová datová struktura a lze ji klasifikovat jako úplný binární strom. Všechny uzly haldy jsou uspořádány v určitém pořadí.
=> Navštivte zde a prohlédněte si sérii školení Java pro všechny
Co se naučíte:
Haldy datová struktura v Javě
V datové struktuře haldy je kořenový uzel porovnán se svými podřízenými a uspořádán podle pořadí. Takže pokud a je kořenový uzel ab je jeho podřízený prvek, pak vlastnost, klíč (a)> = klíč (b) vygeneruje maximální hromadu.
Výše uvedený vztah mezi kořenem a podřízeným uzlem se nazývá „vlastnost haldy“.
V závislosti na pořadí uzlů rodič-dítě je halda obecně dvou typů:
# 1) Max. Hromada :V Max-Heap je klíč kořenového uzlu největší ze všech klíčů v haldě. Mělo by být zajištěno, že stejná vlastnost platí pro všechny podstromy v haldě rekurzivně.
Níže uvedený diagram ukazuje ukázkovou maximální haldu. Kořenový uzel je větší než jeho podřízené objekty.
# 2) Min. Hromada :V případě Min-Heap je klíč kořenového uzlu nejmenší nebo minimální ze všech ostatních klíčů přítomných v haldě. Stejně jako v haldě Max by tato vlastnost měla být rekurzivně pravdivá ve všech ostatních podstromech v haldě.
Příklad, stromu haldy min je zobrazen níže. Jak vidíme, kořenový klíč je nejmenší ze všech ostatních klíčů v haldě.
Strukturu dat haldy lze použít v následujících oblastech:
- Hromady se většinou používají k implementaci prioritních front.
- Zejména min-heap lze použít k určení nejkratších cest mezi vrcholy v Graph.
Jak již bylo zmíněno, datová struktura haldy je kompletní binární strom, který splňuje vlastnost haldy pro root a děti. Tato hromada se také nazývá jako binární hromada .
Binární halda
Binární halda splňuje níže uvedené vlastnosti:
- Binární halda je úplný binární strom. V úplném binárním stromu jsou všechny úrovně kromě poslední úrovně zcela vyplněny. Na poslední úrovni jsou klávesy co nejvíce doleva.
- Splňuje vlastnost haldy. Binární halda může být maximální nebo minimální halda v závislosti na vlastnosti haldy, kterou splňuje.
Binární halda je obvykle reprezentována jako pole. Jelikož se jedná o kompletní binární strom, lze jej snadno reprezentovat jako pole. V maticové reprezentaci binární haldy bude tedy kořenovým prvkem A (0), kde A je pole použité k reprezentaci binární haldy.
Takže obecně pro jakoukoli ithuzel v reprezentaci pole binární haldy, A (i), můžeme reprezentovat indexy dalších uzlů, jak je znázorněno níže.
A ((i-1) / 2) | Představuje nadřazený uzel |
---|---|
Přístup je rychlejší. | Pomalejší než zásobník. |
A ((2 * i) +1) | Představuje levý podřízený uzel |
A ((2 * i) +2) | Představuje pravý podřízený uzel |
Zvažte následující binární haldu:
Reprezentace pole výše uvedené min binární haldy je následující:
Jak je uvedeno výše, halda se prochází podle pořadí na úrovni tj. prvky jsou procházeny zleva doprava na každé úrovni. Když jsou prvky na jedné úrovni vyčerpány, přejdeme na další úroveň.
Dále implementujeme binární haldu v Javě.
Níže uvedený program ukazuje binární hromadu v Javě.
import java.util.*; class BinaryHeap { private static final int d= 2; private int() heap; private int heapSize; //BinaryHeap constructor with default size public BinaryHeap(int capacity){ heapSize = 0; heap = new int( capacity+1); Arrays.fill(heap, -1); } //is heap empty? public boolean isEmpty(){ return heapSize==0; } //is heap full? public boolean isFull(){ return heapSize == heap.length; } //return parent private int parent(int i){ return (i-1)/d; } //return kth child private int kthChild(int i,int k){ return d*i +k; } //insert new element into the heap public void insert(int x){ if(isFull()) throw new NoSuchElementException('Heap is full, No space to insert new element'); heap(heapSize++) = x; heapifyUp(heapSize-1); } //delete an element from the heap at given position public int delete(int x){ if(isEmpty()) throw new NoSuchElementException('Heap is empty, No element to delete'); int key = heap(x); heap(x) = heap(heapSize -1); heapSize--; heapifyDown(x); return key; } //maintain heap property during insertion private void heapifyUp(int i) { int temp = heap(i); while(i>0 && temp > heap(parent(i))){ heap(i) = heap(parent(i)); i = parent(i); } heap(i) = temp; } //maintain heap property during deletion private void heapifyDown(int i){ int child; int temp = heap(i); while(kthChild(i, 1) heap(rightChild)?leftChild:rightChild; } //print the heap public void printHeap() { System.out.print('nHeap = '); for (int i = 0; i Výstup:
nHeap = 7 4 6 1 3 2 5
Min. Hromada v Javě
Hromada min v Javě je kompletní binární strom. V min-haldě je kořenový uzel menší než všechny ostatní uzly v haldě. Obecně je hodnota klíče každého interního uzlu menší nebo stejná jako jeho podřízené uzly.
Pokud jde o maticovou reprezentaci min-haldy, je-li uzel uložen na pozici „i“, je jeho levý podřízený uzel uložen na pozici 2i + 1 a pravý podřízený uzel je na pozici 2i + 2. Pozice (i-1) / 2 vrací svůj nadřazený uzel.
Níže jsou uvedeny různé operace podporované min haldy.
# 1) Vložit (): Zpočátku se na konec stromu přidá nový klíč. Pokud je klíč větší než jeho nadřazený uzel, pak je vlastnost haldy zachována. Jinak musíme projít klíčem nahoru, abychom splnili vlastnost haldy. Operace vložení v minimální haldě zabere čas O (log n).
# 2) extractMin (): Tato operace odebere minimální prvek z haldy. Všimněte si, že vlastnost haldy by měla být zachována po odebrání kořenového prvku (minimální prvek) z haldy. Celá tato operace trvá O (Logn).
# 3) getMin (): getMin () vrací kořen haldy, což je také minimální prvek. Tato operace se provádí v čase O (1).
Níže je uveden příklad stromu pro haldu Min.

Výše uvedený diagram ukazuje strom haldy min. Vidíme, že kořen stromu je minimální prvek ve stromu. Protože kořen je v poloze 0, jeho levé dítě je umístěno na 2 * 0 + 1 = 1 a pravé dítě je na 2 * 0 + 2 = 2.
Algoritmus minimální haldy
Níže je uveden algoritmus pro vytváření min haldy.
procedure build_minheap Array Arr: of size N => array of elements { repeat for (i = N/2 ; i >= 1 ; i--) call procedure min_heapify (A, i); } procedure min_heapify (var A( ) , var i, var N) { var left = 2*i; var right = 2*i+1; var smallest; if(left <= N and A(left) < A( i ) ) smallest = left; else smallest = i; if(right <= N and A(right) < A(smallest) ) smallest = right; if(smallest != i) { swap A( i ) and A( smallest )); call min_heapify (A, smallest,N); } }
Minimální implementace haldy v Javě
Min haldu můžeme implementovat buď pomocí pole nebo prioritních front. Implementace min haldy pomocí prioritních front je výchozí implementací, protože prioritní fronta je implementována jako min haldy.
Následující program Java implementuje min haldu pomocí polí. Zde používáme reprezentaci pole pro haldu a poté použijeme funkci heapify k udržení vlastnosti haldy každého prvku přidaného do haldy. Nakonec haldu zobrazíme.
class Min_Heap { private int() HeapArray; private int size; private int maxsize; private static final int FRONT = 1; //constructor to initialize the HeapArray public Min_Heap(int maxsize) { this.maxsize = maxsize; this.size = 0; HeapArray = new int(this.maxsize + 1); HeapArray(0) = Integer.MIN_VALUE; } // returns parent position for the node private int parent(int pos) { return pos / 2; } // returns the position of left child private int leftChild(int pos) { return (2 * pos); } // returns the position of right child private int rightChild(int pos) { return (2 * pos) + 1; } // checks if the node is a leaf node private boolean isLeaf(int pos) { if (pos >= (size / 2) && pos HeapArray(leftChild(pos)) || HeapArray(pos) > HeapArray(rightChild(pos))) { // swap with left child and then heapify the left child if (HeapArray(leftChild(pos)) = maxsize) { return; } HeapArray(++size) = element; int current = size; while (HeapArray(current) = 1; pos--) { minHeapify(pos); } } // remove and return the heap elment public int remove() { int popped = HeapArray(FRONT); HeapArray(FRONT) = HeapArray(size--); minHeapify(FRONT); return popped; } } class Main{ public static void main(String() arg) { //construct a min heap from given data System.out.println('The Min Heap is '); Min_Heap minHeap = new Min_Heap(7); minHeap.insert(12); minHeap.insert(15); minHeap.insert(30); minHeap.insert(40); minHeap.insert(50); minHeap.insert(90); minHeap.insert(45); minHeap.minHeap(); //display the min heap contents minHeap.display(); //display root node of the min heap System.out.println('The Min val(root node):' + minHeap.remove()); } }
Výstup:

Max. Hromada v Javě
Maximální hromada je také kompletní binární strom. V maximální haldě je kořenový uzel větší nebo roven podřízeným uzlům. Obecně je hodnota jakéhokoli interního uzlu v haldě větší nebo rovna jeho podřízeným uzlům.
Zatímco je maximální halda mapována na pole, pokud je jakýkoli uzel uložen na pozici „i“, pak jeho levé dítě je uloženo na 2i +1 a pravé dítě je uloženo na 2i + 2.
Typická maximální hromada bude vypadat takto:

Ve výše uvedeném diagramu vidíme, že kořenový uzel je největší v haldě a jeho podřízené uzly mají hodnoty menší než kořenový uzel.
Podobně jako min-halda může být maximální halda také reprezentována jako pole.
Pokud je tedy A pole, které představuje Max. Haldu, pak A (0) je kořenový uzel. Podobně, pokud A (i) je libovolný uzel v maximální haldě, jsou následující další sousední uzly, které lze reprezentovat pomocí pole.
- A ((i-1) / 2) představuje nadřazený uzel A (i).
- A ((2i +1)) představuje levý podřízený uzel A (i).
- A (2i + 2) vrací pravý podřízený uzel A (i).
Níže jsou uvedeny operace, které lze provést na haldě Max.
# 1) Vložit: Operace vložení vloží novou hodnotu do stromu maximální haldy. Vkládá se na konec stromu. Pokud je nový klíč (hodnota) menší než jeho nadřazený uzel, pak je vlastnost haldy zachována. Jinak musí být strom heapifikován, aby byla zachována vlastnost haldy.
nejlepší bezplatný stahovač videa z youtube
Časová složitost operace vložení je O (log n).
# 2) ExtractMax: Operace ExtractMax odstraní maximální prvek (root) z maximální haldy. Operace také heapifikuje maximální haldu k udržení vlastnosti haldy. Časová složitost této operace je O (log n).
# 3) getMax: Operace getMax vrací kořenový uzel maximální haldy s časovou složitostí O (1).
Níže uvedený program Java implementuje maximální hromadu. Zde používáme ArrayList k reprezentaci prvků maximální haldy.
import java.util.ArrayList; class Heap { void heapify(ArrayList hT, int i) { int size = hT.size(); int largest = i; int l = 2 * i + 1; int r = 2 * i + 2; if (l hT.get(largest)) largest = l; if (r hT.get(largest)) largest = r; if (largest != i) { int temp = hT.get(largest); hT.set(largest, hT.get(i)); hT.set(i, temp); heapify(hT, largest); } } void insert(ArrayList hT, int newNum) { int size = hT.size(); if (size == 0) { hT.add(newNum); } else { hT.add(newNum); for (int i = size / 2 - 1; i >= 0; i--) { heapify(hT, i); } } } void deleteNode(ArrayList hT, int num) { int size = hT.size(); int i; for (i = 0; i = 0; j--) { heapify(hT, j); } } void printArray(ArrayList array, int size) { for (Integer i : array) { System.out.print(i + ' '); } System.out.println(); } } class Main{ public static void main(String args()) { ArrayList array = new ArrayList(); int size = array.size(); Heap h = new Heap(); h.insert(array, 3); h.insert(array, 4); h.insert(array, 9); h.insert(array, 5); h.insert(array, 2); System.out.println('Max-Heap array: '); h.printArray(array, size); h.deleteNode(array, 4); System.out.println('After deleting an element: '); h.printArray(array, size); } }
Výstup:

Min. Hromada prioritní fronty v Javě
Datovou strukturu prioritní fronty v Javě lze přímo použít k představení min haldy. Ve výchozím nastavení prioritní fronta implementuje min haldu.
Níže uvedený program demonstruje minimální hromadu v Javě pomocí prioritní fronty.
import java.util.*; class Main { public static void main(String args()) { // Create priority queue object PriorityQueue pQueue_heap = new PriorityQueue(); // Add elements to the pQueue_heap using add() pQueue_heap.add(100); pQueue_heap.add(30); pQueue_heap.add(20); pQueue_heap.add(40); // Print the head (root node of min heap) using peek method System.out.println('Head (root node of min heap):' + pQueue_heap.peek()); // Print min heap represented using PriorityQueue System.out.println('
Min heap as a PriorityQueue:'); Iterator iter = pQueue_heap.iterator(); while (iter.hasNext()) System.out.print(iter.next() + ' '); // remove head (root of min heap) using poll method pQueue_heap.poll(); System.out.println('
Min heap after removing root node:'); //print the min heap again Iterator iter2 = pQueue_heap.iterator(); while (iter2.hasNext()) System.out.print(iter2.next() + ' '); } }
Výstup:

Maximální hromada prioritní fronty v Javě
Chcete-li reprezentovat maximální hromadu v Javě pomocí fronty priorit, musíme použít Collection.reverseOrder k obrácení min haldy. Fronta priority přímo představuje min-haldu v Javě.
Implementovali jsme maximální haldu pomocí fronty priorit v níže uvedeném programu.
import java.util.*; class Main { public static void main(String args()) { // Create empty priority queue //with Collections.reverseOrder to represent max heap PriorityQueue pQueue_heap = new PriorityQueue(Collections.reverseOrder()); // Add items to the pQueue using add() pQueue_heap.add(10); pQueue_heap.add(90); pQueue_heap.add(20); pQueue_heap.add(40); // Printing all elements of max heap System.out.println('The max heap represented as PriorityQueue:'); Iterator iter = pQueue_heap.iterator(); while (iter.hasNext()) System.out.print(iter.next() + ' '); // Print the highest priority element (root of max heap) System.out.println('
Head value (root node of max heap):' + pQueue_heap.peek()); // remove head (root node of max heap) with poll method pQueue_heap.poll(); //print the max heap again System.out.println('
Max heap after removing root: '); Iterator iter2 = pQueue_heap.iterator(); while (iter2.hasNext()) System.out.print(iter2.next() + ' '); } }
Výstup:

Hromadit řazení v Javě
Třídění haldy je technika srovnávacího třídění podobná výběru výběru, kde pro každou iteraci vybereme maximální prvek v poli. Třídění haldy využívá datovou strukturu haldy a třídí prvky vytvořením min nebo max haldy z prvků pole, které mají být tříděny.
Již jsme diskutovali, že v haldě min a max obsahuje kořenový uzel minimální a maximální prvek pole. Při třídění haldy je kořenový prvek haldy (min. Nebo max.) Odstraněn a přesunut do seřazeného pole. Zbývající halda se poté heapifikuje, aby se zachovala vlastnost haldy.
Musíme tedy rekurzivně provést dva kroky, abychom dané pole setřídili pomocí haldy.
- Vytvořte hromadu z daného pole.
- Opakovaně odeberte kořenový prvek z haldy a přesuňte jej do seřazeného pole. Heapify zbývající hromadu.
Časová složitost řazení haldy je ve všech případech O (n log n). Složitost prostoru je O (1).
Algoritmus haldy řazení v Javě
Níže jsou uvedeny algoritmy třídění haldy pro třídění daného pole ve vzestupném a sestupném pořadí.
# 1) Algoritmus třídění haldy k seřazení vzestupně:
- Vytvořte maximální hromadu pro dané pole, které chcete třídit.
- Odstraňte kořen (maximální hodnota ve vstupním poli) a přesuňte jej do seřazeného pole. Umístěte poslední prvek do pole v kořenovém adresáři.
- Heapify nový kořen haldy.
- Opakujte kroky 1 a 2, dokud nebude seřazeno celé pole.
# 2) Algoritmus třídění haldy k seřazení v sestupném pořadí:
- Postavte pro dané pole minimální hromádku.
- Odstraňte kořen (minimální hodnota v poli) a vyměňte jej za poslední prvek v poli.
- Heapify nový kořen haldy.
- Opakujte kroky 1 a 2, dokud nebude seřazeno celé pole.
Implementace haldy řazení v Javě
Níže uvedený program Java používá třídění haldy k seřazení pole ve vzestupném pořadí. Za tímto účelem nejprve vytvoříme maximální haldu a poté rekurzivně zaměníme a heapifikujeme kořenový prvek, jak je uvedeno ve výše uvedeném algoritmu.
import java.util.*; class HeapSort{ public void heap_sort(int heap_Array()) { int heap_len = heap_Array.length; // construct max heap for (int i = heap_len / 2 - 1; i >= 0; i--) { heapify(heap_Array, heap_len, i); } // Heap sort for (int i = heap_len - 1; i >= 0; i--) { int temp = heap_Array(0); heap_Array(0) = heap_Array(i); heap_Array(i) = temp; // Heapify root element heapify(heap_Array, i, 0); } } void heapify(int heap_Array(), int n, int i) { // find largest value int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left heap_Array(largest)) largest = left; if (right heap_Array(largest)) largest = right; // recursively heapify and swap if root is not the largest if (largest != i) { int swap = heap_Array(i); heap_Array(i) = heap_Array(largest); heap_Array(largest) = swap; heapify(heap_Array, n, largest); } } } class Main{ public static void main(String args()) { //define input array and print it int heap_Array() = {6,2,9,4,10,15,1,13}; System.out.println('Input Array:' + Arrays.toString(heap_Array)); //call HeapSort method for given array HeapSort hs = new HeapSort(); hs.heap_sort(heap_Array); //print the sorted array System.out.println('Sorted Array:' + Arrays.toString(heap_Array)); } }
Výstup:

Celková časová složitost techniky třídění haldy je O (nlogn). Časová složitost techniky heapify je O (logn). Zatímco časová složitost budování haldy je O (n).
Stack Vs haldy v Javě
Pojďme nyní zmapovat některé rozdíly mezi datovou strukturou Stack a hromadou.
Zásobník Halda Zásobník je lineární datová struktura. Halda je hierarchická datová struktura. Následuje objednávání LIFO (Last In, First Out). Traverz je v pořadí na úrovni. Většinou se používá pro přidělování statické paměti. Používá se pro dynamické přidělování paměti. Paměť je přidělována souvisle. Paměť je alokována na náhodných místech. Velikost zásobníku je omezena podle operačního systému. Operační systém nevynucuje omezení velikosti haldy. Stack má přístup pouze k místním proměnným. Halda má přidělené globální proměnné. Alokace / deallocation paměti je automatická. Alokaci / deallocation je třeba provést ručně programátorem. Zásobník lze implementovat pomocí polí, propojeného seznamu, ArrayList atd. Nebo jiných lineárních datových struktur. Halda je implementována pomocí polí nebo stromů. Náklady na údržbu, pokud jsou nižší. Náročnější na údržbu. Může mít za následek nedostatek paměti, protože je omezená. Žádný nedostatek paměti, ale může trpět fragmentací paměti.
Často kladené otázky
Otázka č. 1) Je zásobník rychlejší než halda?
Odpovědět: Zásobník je rychlejší než halda, protože přístup je v zásobníku lineární ve srovnání s hromadou.
Otázka 2) Na co se halda používá?
Odpovědět: Halda se většinou používá v algoritmech, které nacházejí minimální nebo nejkratší cestu mezi dvěma body, jako je Dijkstrův algoritmus, pro třídění pomocí haldy, pro implementaci prioritních front (min. Halda) atd.
Otázka č. 3) Co je halda? Jaké jsou jeho typy?
Odpovědět: Halda je hierarchická stromová datová struktura. Hromada je kompletní binární strom. Haldy jsou dvou typů, tj. Max haldy, ve které je kořenový uzel největší ze všech uzlů; Min. Hromada, ve které je kořenový uzel nejmenší nebo nejmenší ze všech klíčů.
Otázka č. 4) Jaké jsou výhody haldy oproti zásobníku?
Odpovědět: Hlavní výhoda haldy nad zásobníkem je v haldě, paměť je dynamicky alokována, a proto není omezeno, kolik paměti lze použít. Zadruhé, na zásobník lze přidělit pouze místní proměnné, zatímco na haldě můžeme také přidělit globální proměnné.
Otázka č. 5) Může mít halda duplikáty?
Odpovědět: Ano, neexistují žádná omezení týkající se uzlů s duplicitními klíči v haldě, protože halda je úplný binární strom a nesplňuje vlastnosti binárního vyhledávacího stromu.
Závěr
V tomto kurzu jsme probrali typy haldy a haldy řazení pomocí typů haldy. Také jsme viděli podrobnou implementaci jejích typů v Javě.
=> Podívejte se na průvodce Perfect Java Training Guide zde.
Doporučené čtení
- Výukový program pro grafy Java - Jak implementovat datovou strukturu grafu
- Úvod do datových struktur v C ++
- Třídění haldy v C ++ s příklady
- Datová struktura stromu AVL a haldy v C ++
- Struktura dat binárního stromu v C ++
- Struktura dat fronty v C ++ s ilustrací
- Datová struktura kruhového propojeného seznamu v C ++ s ilustrací
- Základy jazyka Java: Syntaxe jazyka Java, třída Java a základní koncepty Java