Binary heap is a complete binary tree, in which every parent node has a higher (or equal) priority than both of its descendants. If the deepest level of the tree is not fully filled, the nodes are stored in left to right manner.
An important property of an array based implementation of the binary heap is that if the parent is stored at index and the array is indexed starting at 1, than the descendants of the parent are placed at indexes
and
. This property is guaranteed by the fact that the heap does not contain any empty spaces.
The property of being a heap is recursive – every subtree of a heap is also a heap. Thanks to this feature the heap behaves as a priority queue, because the element of the highest priority must be always present at the top of the heap (this can be used for sorting an array – heapsort algorithm).
If the higher value is considered as a higher priority than the heap is called max-heap, on the contrary the min-heap is a heap in which the lower value is considered as a higher priority.
Operations
Repair top
Let's suppose we have a binary heap and we know that the top of the heap is misplaced. The helper repairTop procedure relocates this node to the correct position. The implementation is simple – in every step the procedure compares the parent with of of its descendants, if one of them has a higher priority, than the procedure swaps the nodes. If both descendants have higher priority, than the procedure swaps the parent with the child with higher priority. Now the procedure iteratively repeats the process at he next level until it reaches the deepest level of the heap or the parent has a higher priority than both of his children.
The asymptotic complexity of the repairTop procedure is because the heap has a logarithmic depth.
Heapify
The helper procedure heapify builds heap in a given array. Because the being a heap property is recursive, the procedure has to repair tops of all non-trivial subheap (indexes ). After the termination of the repairing loop the given array represents a binary heap. Asymptotic complexity of the heapify procedure is
.
Insert
The insert operation works in an opposite way than repairTop. The new element is added at the end of the heap and it ascends through the heap while it has a higher priority than its parent. Asymptotic complexity of the inserion is .
Top
The operation top returns the element of the heap with the highest priority. Because it just returns the first element of the array, the asymptotic complexity of this operation is constant – .
Return top
The return top operation retrieves and deletes the element of the heap with the highest priority. In fact it swaps the top element with the last one, shorthens the heap (decrements its size variable) and repairs the top of the heap. The asymptotic complexity of this approach is equal to the complexity of the repairTop operation – .
Merge
The merge operation merges two heaps into one – it creates one array and copies all elements of both heaps into it. Than the algorithm heapifies the array. The asymptotic complexity of the merge operation is , where
is the size of the first array and
is the size of the second array.
Code
001.
/**
002.
* Binary heap (min-heap)
003.
* @author Pavel Micka
004.
*/
005.
public
class
BinaryHeap {
006.
007.
private
int
[] array;
008.
private
int
size;
// size of the array (keep in mind that we are indexing from 1)
009.
010.
/**
011.
* Constructor
012.
* @param arraySize maximal size of the heap
013.
*/
014.
public
BinaryHeap(
int
arraySize) {
015.
this
.array =
new
int
[arraySize +
1
];
// first index will be always empty
016.
this
.size =
0
;
017.
}
018.
019.
/**
020.
* Konstruktor
021.
* @param arraySize velikost haldy
022.
*/
023.
public
BinaryHeap(
int
[] source) {
024.
this
.array =
new
int
[source.length +
1
];
// first index will be always empty
025.
System.arraycopy(source,
0
, array,
1
, source.length);
026.
this
.size =
0
;
027.
}
028.
029.
/**
030.
* Perform merging of the heaps
031.
* @param heap heap to be merged with this heap
032.
*/
033.
public
void
merge(BinaryHeap heap) {
034.
int
[] newArray =
new
int
[
this
.size + heap.size +
1
];
035.
036.
System.arraycopy(array,
1
, newArray,
1
,
this
.size);
037.
System.arraycopy(heap.array,
1
, newArray,
this
.size +
1
, heap.size);
038.
039.
size =
this
.size + heap.size;
040.
array = newArray;
041.
heapify(newArray);
042.
}
043.
044.
/**
045.
* Return array of all elements in this heap
046.
* @return array of all elements in this heap
047.
*/
048.
public
int
[] getAll() {
049.
return
Arrays.copyOfRange(array,
1
,
this
.size +
1
);
050.
}
051.
052.
/**
053.
* Insert the array to the heap
054.
* @param i element to be inserted
055.
*/
056.
public
void
insert(
int
i) {
057.
size++;
058.
int
index =
this
.size;
059.
while
(i < array[index /
2
] && index !=
0
) {
060.
array[index] = array[index /
2
];
061.
index /=
2
;
062.
}
063.
array[index] = i;
064.
}
065.
066.
public
int
top() {
067.
if
(getSize() ==
0
) {
068.
throw
new
IllegalStateException(
"The heap is empty"
);
069.
}
070.
return
array[
1
];
071.
}
072.
073.
/**
074.
* Remove and retrive the top of the heap
075.
* @return element with the highest priority
076.
*/
077.
public
int
returnTop() {
078.
if
(getSize() ==
0
) {
079.
throw
new
IllegalStateException(
"The heap is empty"
);
080.
}
081.
int
tmp = array[
1
];
082.
array[
1
] = array[
this
.size];
083.
size--;
084.
repairTop(
this
.size,
1
);
085.
return
tmp;
086.
}
087.
088.
@Override
089.
public
String toString() {
090.
StringBuilder builder =
new
StringBuilder();
091.
for
(
int
i =
1
; i <=
this
.size; i++) {
092.
builder.append(array[i]).append(
" "
);
093.
}
094.
return
builder.toString();
095.
}
096.
097.
/**
098.
* @return the size
099.
*/
100.
public
int
getSize() {
101.
return
size;
102.
}
103.
104.
/**
105.
* Create the heap using the given array
106.
* @param array array
107.
*/
108.
private
void
heapify(
int
[] array) {
109.
for
(
int
i = array.length /
2
; i >
0
; i--) {
110.
repairTop(
this
.size, i);
111.
}
112.
}
113.
114.
/**
115.
* Place the top of the heap to the correct position in the heap
116.
* @param bottom last index of the array which can be touched
117.
* @param topIndex index of the top of the heap
118.
*/
119.
private
void
repairTop(
int
bottom,
int
topIndex) {
120.
int
tmp = array[topIndex];
121.
int
succ = topIndex *
2
;
122.
if
(succ < bottom && array[succ] > array[succ +
1
]) {
123.
succ++;
124.
}
125.
126.
while
(succ <= bottom && tmp > array[succ]) {
127.
array[topIndex] = array[succ];
128.
topIndex = succ;
129.
succ = succ *
2
;
130.
if
(succ < bottom && array[succ] > array[succ +
1
]) {
131.
succ++;
132.
}
133.
}
134.
array[topIndex] = tmp;
135.
}
136.
}