Skip to content

Commit 798eec0

Browse files
author
Haoyang Chen
authored
add c++ heap code
1 parent 613a77a commit 798eec0

File tree

1 file changed

+166
-0
lines changed
  • zh-hans/basics_data_structure

1 file changed

+166
-0
lines changed

zh-hans/basics_data_structure/heap.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,169 @@ class MaxHeap:
7171
self._sink(self.heap, 0)
7272
return item
7373
```
74+
## C++
75+
```
76+
#ifndef HEAP_H
77+
#define HEAP_H
78+
79+
#include <algorithm>
80+
#include <functional>
81+
#include <stdexcept>
82+
#include <unordered_map>
83+
#include <utility>
84+
#include <vector>
85+
template <typename T, typename TComparator = std::equal_to<T>,
86+
typename PComparator = std::less<double>,
87+
typename Hasher = std::hash<T> >
88+
class Heap {
89+
public:
90+
/// Constructs an m-ary heap. M should be >= 2
91+
Heap(int m = 2, const PComparator &c = PComparator(),
92+
const Hasher &hash = Hasher(), const TComparator &tcomp = TComparator());
93+
94+
/// Destructor as needed
95+
~Heap();
96+
97+
/// Adds an item with the provided priority
98+
void push(double pri, const T &item);
99+
100+
/// returns the element at the top of the heap
101+
/// max (if max-heap) or min (if min-heap)
102+
T const &top() const;
103+
104+
/// Removes the top element
105+
void pop();
106+
107+
/// returns true if the heap is empty
108+
bool empty() const;
109+
110+
/// decreaseKey reduces the current priority of
111+
/// item to newpri, moving it up in the heap
112+
/// as appropriate.
113+
void decreaseKey(double newpri, const T &item);
114+
115+
private:
116+
/// Add whatever helper functions you need below
117+
void trickleUp(int loc);
118+
void trickleDown(int loc);
119+
120+
// These should be all the data members you need.
121+
std::vector<std::pair<double, T> > store_;
122+
int m_; // degree
123+
PComparator c_;
124+
std::unordered_map<T, size_t, Hasher, TComparator> keyToLocation_;
125+
};
126+
127+
// Complete
128+
template <typename T, typename TComparator, typename PComparator,
129+
typename Hasher>
130+
Heap<T, TComparator, PComparator, Hasher>::Heap(int m, const PComparator &c,
131+
const Hasher &hash,
132+
const TComparator &tcomp)
133+
: store_(), m_(m), c_(c), keyToLocation_(100, hash, tcomp) {
134+
}
135+
136+
// Complete
137+
template <typename T, typename TComparator, typename PComparator,
138+
typename Hasher>
139+
Heap<T, TComparator, PComparator, Hasher>::~Heap() {
140+
}
141+
142+
template <typename T, typename TComparator, typename PComparator,
143+
typename Hasher>
144+
void Heap<T, TComparator, PComparator, Hasher>::push(double priority,
145+
const T &item) {
146+
// You complete.
147+
std::pair<double, T> temp(priority, item);
148+
store_.push_back(temp);
149+
keyToLocation_[item] = store_.size();
150+
// insert(std::make_pair(item, store_.size()));
151+
trickleUp(store_.size()-1);
152+
}
153+
154+
template <typename T, typename TComparator, typename PComparator,
155+
typename Hasher>
156+
void Heap<T, TComparator, PComparator, Hasher>::trickleUp(int loc) {
157+
int parent = (loc-1)/m_;
158+
while(parent >= 0 && c_(store_[loc].first, store_[parent].first)) {
159+
//swap loc with parent
160+
std::pair<double, T> temp = store_[loc];
161+
store_[loc] = store_[parent];
162+
store_[parent] = temp;
163+
double to_swap = keyToLocation_[store_[loc].second];
164+
keyToLocation_[store_[loc].second] = keyToLocation_[store_[parent].second];
165+
keyToLocation_[store_[parent].second] = to_swap;
166+
loc = parent;
167+
parent = (loc-1)/m_;
168+
}
169+
}
170+
171+
172+
template <typename T, typename TComparator, typename PComparator,
173+
typename Hasher>
174+
void Heap<T, TComparator, PComparator, Hasher>::decreaseKey(double priority,
175+
const T &item) {
176+
std::pair<double, T> temp = store_[keyToLocation_[item]];
177+
temp.first = priority;
178+
trickleUp(keyToLocation_[item]);
179+
}
180+
181+
template <typename T, typename TComparator, typename PComparator,
182+
typename Hasher>
183+
T const &Heap<T, TComparator, PComparator, Hasher>::top() const {
184+
// Here we use exceptions to handle the case of trying
185+
// to access the top element of an empty heap
186+
if (empty()) {
187+
throw std::logic_error("can't top an empty heap");
188+
}
189+
return store_[0].second;
190+
}
191+
192+
/// Removes the top element
193+
template <typename T, typename TComparator, typename PComparator,
194+
typename Hasher>
195+
void Heap<T, TComparator, PComparator, Hasher>::pop() {
196+
if (empty()) {
197+
throw std::logic_error("can't pop an empty heap");
198+
}
199+
store_[0] = store_[store_.size()-1];
200+
keyToLocation_.erase(store_[0].second);
201+
store_.pop_back();
202+
if(empty()) return;
203+
trickleDown(0);
204+
}
205+
template <typename T, typename TComparator, typename PComparator,
206+
typename Hasher>
207+
void Heap<T, TComparator, PComparator, Hasher>::trickleDown(int loc) {
208+
if (loc*m_+1 > store_.size()-1) return;
209+
int smallerChild = m_*loc+1; // start w/ left
210+
for (size_t i = 1; i < m_; i++) {
211+
if (m_*loc+i < store_.size()) {//if the right exist
212+
int rChild = m_*loc+i+1;
213+
if(c_(store_[rChild].first, store_[smallerChild].first)) {
214+
smallerChild = rChild;
215+
}
216+
}
217+
}
218+
if(c_(store_[smallerChild].first, store_[loc].first)) {
219+
//swap smallerChild and loc
220+
std::pair<double, T> temp = store_[loc];
221+
store_[loc] = store_[smallerChild];
222+
store_[smallerChild] = temp;
223+
double to_swap = keyToLocation_[store_[loc].second];
224+
keyToLocation_[store_[loc].second] = keyToLocation_[store_[smallerChild].second];
225+
keyToLocation_[store_[smallerChild].second] = to_swap;
226+
trickleDown(smallerChild);
227+
}
228+
}
229+
230+
231+
/// returns true if the heap is empty
232+
template <typename T, typename TComparator, typename PComparator,
233+
typename Hasher>
234+
bool Heap<T, TComparator, PComparator, Hasher>::empty() const {
235+
return store_.empty();
236+
}
237+
238+
#endif
239+
```

0 commit comments

Comments
 (0)