Skip to content

Commit d8a2d8d

Browse files
author
Colin Lin
committed
add heap implementation
1 parent 6c76e7f commit d8a2d8d

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

Algon/dstruct/Heap.h

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#pragma once
2+
3+
#include <initializer_list>
4+
#include <vector>
5+
#include <iostream>
6+
#include <functional>
7+
#include <type_traits>
8+
#include <cassert>
9+
10+
#define PARENT(i) ((i)>>1)
11+
#define LCHILD(i) ((i)<<1)
12+
13+
namespace colinli{
14+
namespace algon{
15+
16+
17+
18+
template<typename TKey, typename Comparer = std::less<TKey> >
19+
class Heap {
20+
public:
21+
/** default constructor*/
22+
23+
24+
Heap(const std::initializer_list <TKey> &list) {
25+
_init();
26+
for (auto key : list)
27+
add(key);
28+
}
29+
Heap(){
30+
_init();
31+
}
32+
33+
///template <typename TKey>
34+
friend
35+
void heapSwap(Heap<TKey, Comparer>& h1, Heap<TKey, Comparer> & h2);
36+
37+
Heap<TKey>& operator=(Heap<TKey> other){
38+
heapSwap(*this, other);
39+
return *this;
40+
}
41+
42+
43+
void add(const TKey& key)
44+
{
45+
elems.push_back(key);
46+
int N = elems.size() - 1;
47+
//std::cout<<"N="<<N<<" \n";
48+
_swim(N);
49+
//std::cout<<"\n[DEBUG] print content: ";
50+
// _print();
51+
52+
}
53+
54+
TKey top() const
55+
{
56+
assert(elems.size() > 1);
57+
return elems.at(1);
58+
}
59+
60+
size_t size() const
61+
{
62+
63+
return elems.size() - 1;
64+
}
65+
TKey pop()
66+
{
67+
TKey top = elems.at(1);
68+
int N = elems.size() - 1;
69+
_swap(1, N);
70+
elems.pop_back();
71+
_sink(1);
72+
return top;
73+
74+
}
75+
76+
bool empty() const
77+
{
78+
return elems.size() == 1;
79+
}
80+
81+
void poppush(TKey key)
82+
{
83+
this->pop();
84+
this->add(key);
85+
}
86+
87+
88+
private:
89+
90+
///size_t N; // index of tail element
91+
std::vector<TKey> elems;
92+
93+
void _print(){
94+
for (int i = 1; i < elems.size(); i++)
95+
std::cout << elems.at(i) << ",";
96+
}
97+
98+
/**
99+
* disuse zero index element
100+
*/
101+
void _init() {
102+
//leave index 0 unused
103+
TKey _ = TKey();
104+
elems.push_back(_);
105+
}
106+
107+
void _swap(int i, int j){
108+
assert(i >= 0 && i < elems.size());
109+
assert(j >= 0 && j < elems.size());
110+
TKey t = elems[i];
111+
elems[i] = elems[j];
112+
elems[j] = t;
113+
}
114+
115+
116+
void _swim(int i){
117+
int p;
118+
for (int j = i; j > 1 && less(j, (p = PARENT(j))); j = p) {
119+
_swap(j, p);
120+
}
121+
}
122+
123+
void _sink(int i){
124+
int c;
125+
int N = elems.size() - 1;
126+
for (int j = i; (c = LCHILD(j)) <= N; j = c) {
127+
if (c + 1 <= N && less(c + 1, c))
128+
c++;
129+
if (less(j, c))
130+
break;
131+
//else swap and continue
132+
_swap(c, j);
133+
}
134+
}
135+
136+
bool less(int me, int other){
137+
Comparer comp;
138+
return comp(elems.at(me), elems.at(other));
139+
}
140+
141+
142+
};
143+
144+
template<typename TKey, typename Comparer>
145+
void heapSwap(Heap<TKey, Comparer>& h1, Heap<TKey, Comparer> & h2)
146+
{
147+
h1.elems.swap(h2.elems);
148+
}
149+
150+
151+
template <typename T>
152+
using MaxHeap = Heap<T, std::greater<T> >;
153+
154+
template <typename T>
155+
using MinHeap = Heap<T, std::less<T> >;
156+
157+
158+
template <typename TKey, typename Less = std::less<TKey>, typename Greater = std::greater<TKey> >
159+
class MedianHeap
160+
{
161+
public:
162+
MedianHeap()
163+
{
164+
assert(minheap.empty() && maxheap.empty());
165+
}
166+
167+
size_t size() const
168+
{
169+
return minheap.size() + maxheap.size();
170+
}
171+
void add(TKey key)
172+
{
173+
auto N = size();
174+
175+
if (N % 2 == 0)
176+
{
177+
//right now the maxhp and minhp have equal #keys
178+
maxheap.add(key);
179+
if (minheap.empty())
180+
return;
181+
if (maxheap.top() > minheap.top()){
182+
auto toMin = maxheap.pop();
183+
auto toMax = minheap.pop();
184+
minheap.add(toMin);
185+
maxheap.add(toMax);
186+
187+
}
188+
}
189+
else
190+
//maxheap has one more key, add this to minhp
191+
minheap.add(key);
192+
193+
194+
}
195+
196+
friend
197+
std::istream& operator>>(std::istream& is, MedianHeap<TKey, Less, Greater> & medianhp)
198+
{
199+
TKey e;
200+
is >> e;
201+
medianhp.add(e);
202+
return is;
203+
}
204+
205+
206+
typename std::enable_if<std::is_arithmetic<TKey>::value, TKey>::type
207+
getMedian() const
208+
{
209+
210+
auto N = size();
211+
212+
213+
if (N % 2 == 0)
214+
return (minheap.top() + maxheap.top()) / static_cast<TKey>(2);
215+
else
216+
return maxheap.top();
217+
}
218+
219+
220+
221+
private:
222+
Heap<TKey, Less> minheap;
223+
Heap<TKey, Greater> maxheap;
224+
};
225+
226+
} // end of algon namespace
227+
}// end of colinli namespace

0 commit comments

Comments
 (0)