-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheap.h
More file actions
130 lines (105 loc) · 3.05 KB
/
heap.h
File metadata and controls
130 lines (105 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef _HEAP_H_
#define _HEAP_H_
#include <vector>
#include <algorithm>
// Only assumes the key type K is totally ordered and comparable via <
template <class T, class K>
struct HeapItem {
T item;
K key;
};
template <class T, class K>
class BinaryHeap {
public:
// constructor not required because the only "initialization"
// is through the constructor of the variable "heap" which is called by default
// return the minimum element in the heap
HeapItem<T, K> min() const;
// insert an item with the given key
// if the item is already in the heap, will still insert a new copy with this key
void insert(const T& item, const K& key);
// pop the minimum item from the heap
void popMin();
// returns the number of items held in the heap
int size() const;
private:
// the array holding the heap
std::vector< HeapItem<T, K> > heap;
// will fix the heap property at index i and recurse with its parent
void fixHeapUp(int i);
// will fix the heap property at index i and recurse with the child
// that received i's item (if appropriate)
void fixHeapDown(int i);
};
template <class T, class K>
HeapItem<T, K> BinaryHeap<T, K>::min() const {
return heap[0];
}
template <class T, class K>
void BinaryHeap<T, K>::insert(const T& item, const K& key) {
HeapItem<T, K> node = {item, key};
// add the new item to the end of the heap
heap.push_back(node);
// fix the heap property
fixHeapUp(heap.size()-1);
}
template <class T, class K>
void BinaryHeap<T, K>::popMin() {
// move the last item of the last layer to the top
// if the heap has size 1, this just pops it
heap[0] = heap.back();
heap.pop_back();
// if there is anything left in the heap, fix the heap property
if (heap.size() > 0) {
fixHeapDown(0);
}
}
template <class T, class K>
int BinaryHeap<T, K>::size() const {
return heap.size();
}
template <class T, class K>
void BinaryHeap<T, K>::fixHeapUp(int i) {
while (i > 0) {
int pi = (i-1)>>1; // parent index
// if i's key is smaller than its parent's key, swap it and go up
if (heap[i].key < heap[pi].key) {
std::swap(heap[i], heap[pi]);
i = pi;
}
else {
// otherwise, no more fixing needs to be done
return;
}
}
}
template <class T, class K>
void BinaryHeap<T, K>::fixHeapDown(int i) {
while (true) {
// calculate indices of the two children
int lchild = (i<<1)+1, rchild = (i<<1)+2;
// if no children, no problem
if (lchild >= heap.size()) {
return;
}
int min_child;
// identify the child with the minimum key, being careful
// to handle the case where there is no right child
if (rchild >= heap.size() || heap[lchild].key <= heap[rchild].key) {
min_child = lchild;
}
else {
min_child = rchild;
}
// if there is a violation of the heap property for i, swap its node
// with the node held by the minimum-key child and repeat with this child
if (heap[min_child].key < heap[i].key) {
std::swap(heap[i], heap[min_child]);
i = min_child;
}
else {
return;
}
}
}
#endif