binary_heap.h
Go to the documentation of this file.
1 /*
2  * This file is part of the alglib project.
3  *
4  * (c) Divyanshu Kakwani <divkakwani@gmail.com>
5  *
6  * For the full copyright and license information, please view the LICENSE file
7  * that was distributed with this source code.
8  */
9 
10 #ifndef _BINARY_HEAP_H
11 #define _BINARY_HEAP_H
12 
13 #include <boost/concept_check.hpp>
14 #include <iostream>
15 #include <vector>
16 #include <algorithm>
17 #include <map>
18 #include <alglib/heap/heap.h>
19 
20 
21 namespace alglib {
22 namespace heap {
23 
24 // FIXME FIXME FIXME
25 // Duplicates not allowed
26 
27 // TODO(divkakwani): Convert to rvalue-references
28 
29 template<typename elt_t, typename key_t>
30 class binary_heap : public min_heap<elt_t, key_t> {
31  BOOST_CONCEPT_ASSERT((boost::LessThanComparable<elt_t>));
32  BOOST_CONCEPT_ASSERT((boost::LessThanComparable<key_t>));
33 
34  public:
35  /* typedefs */
36  typedef elt_t elt_type;
37  typedef key_t key_type;
38 
39  /* Default Ctor */
40  binary_heap();
41 
42  /* aggregate initialization */
43  template<typename InputIter>
44  explicit binary_heap(InputIter elt_first, InputIter elt_last, InputIter key_first);
45 
46 
47  void insert(const elt_t& elt, const key_t& key);
48 
49  /* get the root */
50  const elt_t& get_min_elt() const;
51  const key_t& get_min_key() const;
52 
53  /* remove the root */
54  void delete_min();
55  void replace(const elt_t& elt, const key_t& key);
56 
57  /* Inspection */
58  int size() const override { return __sz; }
59  bool empty() const override { return __sz == 0; }
60 
61  /* Internal modification */
62  void update_key(const elt_t& elt, const key_t& key);
63 
64 
65  private:
66  /* `node` is wrapper around the key with an additional pointer to
67  * the element which it is associated with.
68  */
69  struct node_t {
70  key_t key;
71  typename std::map<elt_t, int>::iterator elt_it;
72  bool operator<(const node_t& other) const { return key < other.key; }
73  };
74 
75  /* `nodeof` stores the node corresponding to element inserted in the heap.
76  * The heap only contains the nodes. To go from an element to its
77  * node or from a node back to its element, we'll have to go through
78  * `nodeof`
79  */
80  std::map<elt_t, int> nodeof;
81 
82  /* The heap is stored in this array */
83  std::vector<node_t> heaparr;
84  int __sz;
85 
86  typename std::map<elt_t, int>::iterator make_entry(const elt_t& elt) {
87  if (nodeof.find(elt) == nodeof.end())
88  nodeof[elt] = -1;
89  return nodeof.find(elt);
90  }
91  void update_entry(int idx) { (heaparr[idx].elt_it)->second = idx; }
92 
93  /* Helper functions */
94  inline int __parent(int node) { return (node - 1) / 2; }
95  inline int __left_child(int node) { return node * 2 + 1; }
96  inline int __right_child(int node) { return node * 2 + 2; }
97  void __sift_up(int node);
98  void __sift_down(int node);
99 };
100 
101 template<typename elt_t, typename key_t>
103  __sz = 0;
104 }
105 
106 template<typename elt_t, typename key_t>
107 template<typename InputIter>
109  InputIter elt_last,
110  InputIter key_first) {
111  __sz = 0;
112  while (elt_first != elt_last) {
113  auto loc = make_entry(*elt_first);
114  heaparr[__sz++] = node_t {*key_first, loc};
115  ++elt_first;
116  }
117 
118  // Heapify the __stash
119  for (int i = __sz / 2; i >= 0; i--)
120  __sift_down(i);
121 }
122 
123 template<typename elt_t, typename key_t>
124 void binary_heap<elt_t, key_t>::insert(const elt_t& elt,
125  const key_t& key) {
126  auto loc = make_entry(elt);
127  heaparr.push_back(node_t {key, loc});
128  __sift_up(__sz);
129  ++__sz;
130 }
131 
132 
133 template<typename elt_t, typename key_t>
135  return (heaparr[0].elt_it)->first;
136 }
137 
138 
139 template<typename elt_t, typename key_t>
141  return heaparr[0].key;
142 }
143 
144 template<typename elt_t, typename key_t>
146  nodeof.erase(heaparr[0].elt_it);
147  std::swap(heaparr[0], heaparr[__sz - 1]);
148  --__sz;
149  __sift_down(0);
150 }
151 
152 template<typename elt_t, typename key_t>
154  const key_t& key) {
155  if (__sz == 0)
156  throw std::underflow_error("Empty heap");
157  auto loc = make_entry(elt);
158  nodeof.erase(heaparr[0].elt_it); // Clean up the elt from nodeof map
159  heaparr[0] = node_t {key, loc};
160  __sift_down(0);
161 }
162 
163 template<typename elt_t, typename key_t>
165  const key_t& key) {
166  if (nodeof.find(elt) == nodeof.end())
167  throw std::domain_error("The element doesn't exist");
168  int index_in_heap = nodeof[elt];
169  heaparr[index_in_heap] = node_t {key, heaparr[index_in_heap].elt_it};
170  __sift_up(index_in_heap);
171  __sift_down(index_in_heap);
172 }
173 
174 template<typename elt_t, typename key_t>
176  /*
177  * Store the node in a temp and move all the other nodes encountered
178  * while going upwards down and finally put the temp in the upmost place.
179  */
180  node_t temp = heaparr[node];
181  while (node != 0 && temp < heaparr[__parent(node)]) {
182  heaparr[node] = heaparr[__parent(node)];
183  update_entry(node);
184  node = __parent(node);
185  }
186  heaparr[node] = temp;
187  update_entry(node);
188 }
189 
190 template<typename elt_t, typename key_t>
191 void binary_heap<elt_t, key_t>::__sift_down(int node) {
192  int min_node = node;
193  int left_child = __left_child(node);
194  int right_child = __right_child(node);
195 
196  if (left_child < __sz && heaparr[left_child] < heaparr[min_node])
197  min_node = left_child;
198  if (right_child < __sz && heaparr[right_child] < heaparr[min_node])
199  min_node = right_child;
200 
201  if (min_node != node) {
202  std::swap(heaparr[node], heaparr[min_node]);
203  update_entry(node);
204  update_entry(min_node);
205  __sift_down(min_node);
206  }
207 }
208 
209 /* Partial specialization of the heap class for the case when the prioritizing
210  * order is the natural order itself.
211  */
212 template<typename elt_t>
214  private:
216 
217  public:
218  void insert(const elt_t& elt) { heap.insert(elt, elt); }
219 
220  /* get the root */
221  const elt_t& get_min() const { return heap.get_min_elt(); }
222 
223  /* remove the root */
224  void delete_min() { heap.delete_min(); }
225  void replace(const elt_t& elt) { heap.replace(elt, elt); }
226 
227  /* Inspection */
228  int size() const { return heap.size(); }
229  bool empty() const { return heap.empty(); }
230 };
231 
232 } // end heap namespace
233 } // end alglib namespace
234 
235 #endif // _BINARY_HEAP_H
key_t key_type
Definition: binary_heap.h:37
void replace(const elt_t &elt, const key_t &key)
Definition: binary_heap.h:153
void delete_min()
Definition: binary_heap.h:224
bool empty() const override
Definition: binary_heap.h:59
Definition: bimap.h:17
void insert(const elt_t &elt)
Definition: binary_heap.h:218
Definition: binary_heap.h:213
binary_heap()
Definition: binary_heap.h:102
const elt_t & get_min_elt() const
Definition: binary_heap.h:134
const elt_t & get_min() const
Definition: binary_heap.h:221
void update_key(const elt_t &elt, const key_t &key)
Definition: binary_heap.h:164
Definition: binary_heap.h:30
Definition: heap.h:65
void delete_min()
Definition: binary_heap.h:145
void replace(const elt_t &elt)
Definition: binary_heap.h:225
const key_t & get_min_key() const
Definition: binary_heap.h:140
int size() const
Definition: binary_heap.h:228
elt_t elt_type
Definition: binary_heap.h:36
int size() const override
Definition: binary_heap.h:58
void insert(const elt_t &elt, const key_t &key)
Definition: binary_heap.h:124
bool empty() const
Definition: binary_heap.h:229