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