GteMinHeap.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <GTEngineDEF.h>
11 #include <vector>
12 
13 // A min-heap is a binary tree whose nodes have weights and with the
14 // constraint that the weight of a parent node is less than or equal to the
15 // weights of its children. This data structure may be used as a priority
16 // queue. If the std::priority_queue interface suffices for your needs, use
17 // that instead. However, for some geometric algorithms, that interface is
18 // insufficient for optimal performance. For example, if you have a polyline
19 // vertices that you want to decimate, each vertex's weight depends on its
20 // neighbors' locations. If the minimum-weight vertex is removed from the
21 // min-heap, the neighboring vertex weights must be updated--something that
22 // is O(1) time when you store the vertices as a doubly linked list. The
23 // neighbors are already in the min-heap, so modifying their weights without
24 // removing then from--and then reinserting into--the min-heap requires they
25 // must be moved to their proper places to restore the invariant of the
26 // min-heap. With std::priority_queue, you have no direct access to the
27 // modified vertices, forcing you to search for those vertices, remove them,
28 // update their weights, and re-insert them. The min-heap implementation here
29 // does support the update without removal and reinsertion.
30 //
31 // The ValueType represents the weight and it must support comparisons
32 // "<" and "<=". Additional information can be stored in the min-heap for
33 // convenient access; this is stored as the KeyType. In the (open) polyline
34 // decimation example, the KeyType is a structure that stores indices to
35 // a vertex and its neighbors. The following code illustrates the creation
36 // and use of the min-heap. The Weight() function is whatever you choose to
37 // guide which vertices are removed first from the polyline.
38 //
39 // struct Vertex { int previous, current, next; };
40 // int numVertices = <number of polyline vertices>;
41 // std::vector<Vector<N, Real>> positions(numVertices);
42 // <assign all positions[*]>;
43 // MinHeap<Vertex, Real> minHeap(numVertices);
44 // std::vector<MinHeap<Vertex, Real>::Record*> records(numVertices);
45 // for (int i = 0; i < numVertices; ++i)
46 // {
47 // Vertex vertex;
48 // vertex.previous = (i + numVertices - 1) % numVertices;
49 // vertex.current = i;
50 // vertex.next = (i + 1) % numVertices;
51 // records[i] = minHeap.Insert(vertex, Weight(positions, vertex));
52 // }
53 //
54 // while (minHeap.GetNumElements() >= 2)
55 // {
56 // Vertex vertex;
57 // Real weight;
58 // minHeap.Remove(vertex, weight);
59 // <consume the 'vertex' according to your application's needs>;
60 //
61 // // Remove 'vertex' from the doubly linked list.
62 // Vertex& vp = records[vertex.previous]->key;
63 // Vertex& vc = records[vertex.current]->key;
64 // Vertex& vn = records[vertex.next]->key;
65 // vp.next = vc.next;
66 // vn.previous = vc.previous;
67 //
68 // // Update the neighbors' weights in the min-heap.
69 // minHeap.Update(records[vertex.previous], Weight(positions, vp));
70 // minHeap.Update(records[vertex.next], Weight(positions, vn));
71 // }
72 
73 namespace gte
74 {
75 
76 template <typename KeyType, typename ValueType>
77 class MinHeap
78 {
79 public:
80  struct Record
81  {
82  KeyType key;
83  ValueType value;
84  int index;
85  };
86 
87  // Construction. The record 'value' members are uninitialized for native
88  // types chosen for ValueType. If ValueType is of class type, then the
89  // default constructor is used to set the 'value' members.
90  MinHeap(MinHeap const& minHeap);
91  MinHeap(int maxElements = 0);
92 
93  // Assignment.
94  MinHeap& operator=(MinHeap const& minHeap);
95 
96  // Clear the min-heap so that it has the specified max elements,
97  // mNumElements is zero, and mPointers are set to the natural ordering
98  // of mRecords.
99  void Reset(int maxElements);
100 
101  // Get the remaining number of elements in the min-heap. This number is
102  // in the range {0..maxElements}.
103  inline int GetNumElements() const;
104 
105  // Get the root of the min-heap. The return value is 'true' whenever the
106  // min-heap is not empty. This function reads the root but does not
107  // remove the element from the min-heap.
108  inline bool GetMinimum(KeyType& key, ValueType& value) const;
109 
110  // Insert into the min-heap the 'value' that corresponds to the 'key'.
111  // The return value is a pointer to the heap record that stores a copy of
112  // 'value', and the pointer value is constant for the life of the min-heap.
113  // If you must update a member of the min-heap, say, as illustrated in the
114  // polyline decimation example, pass the pointer to Update:
115  // auto* valueRecord = minHeap.Insert(key, value);
116  // <do whatever>;
117  // minHeap.Update(valueRecord, newValue).
118  Record* Insert(KeyType const& key, ValueType const& value);
119 
120  // Remove the root of the heap and return its 'key' and 'value members.
121  // The root contains the minimum value of all heap elements. The return
122  // value is 'true' whenever the min-heap was not empty before the Remove
123  // call.
124  bool Remove(KeyType& key, ValueType& value);
125 
126  // The value of a heap record must be modified through this function call.
127  // The side effect is that the heap is updated accordingly to restore the
128  // data structure to a min-heap. The input 'record' should be a pointer
129  // returned by Insert(value); see the comments for the Insert() function.
130  void Update(Record* record, ValueType const& value);
131 
132  // Support for debugging. The functions test whether the data structure
133  // is a valid min-heap.
134  bool IsValid() const;
135 
136 private:
137  // A 2-level storage system is used. The pointers have two roles.
138  // Firstly, they are unique to each inserted value in order to support
139  // the Update() capability of the min-heap. Secondly, they avoid
140  // potentially expensive copying of Record objects as sorting occurs in
141  // the heap.
143  std::vector<Record> mRecords;
144  std::vector<Record*> mPointers;
145 };
146 
147 
148 template <typename KeyType, typename ValueType>
150 {
151  Reset(maxElements);
152 }
153 
154 template <typename KeyType, typename ValueType>
156 {
157  *this = minHeap;
158 }
159 
160 template <typename KeyType, typename ValueType>
162 {
163  mNumElements = minHeap.mNumElements;
164  mRecords = minHeap.mRecords;
165  mPointers.resize(minHeap.mPointers.size());
166  for (auto& record : mRecords)
167  {
168  mPointers[record.index] = &record;
169  }
170  return *this;
171 }
172 
173 template <typename KeyType, typename ValueType>
175 {
176  mNumElements = 0;
177  if (maxElements > 0)
178  {
179  mRecords.resize(maxElements);
180  mPointers.resize(maxElements);
181  for (int i = 0; i < maxElements; ++i)
182  {
183  mPointers[i] = &mRecords[i];
184  mPointers[i]->index = i;
185  }
186  }
187  else
188  {
189  mRecords.clear();
190  mPointers.clear();
191  }
192 }
193 
194 template <typename KeyType, typename ValueType>
196 {
197  return mNumElements;
198 }
199 
200 template <typename KeyType, typename ValueType>
201 inline bool MinHeap<KeyType, ValueType>::GetMinimum(KeyType& key, ValueType& value) const
202 {
203  if (mNumElements > 0)
204  {
205  key = mPointers[0]->key;
206  value = mPointers[0]->value;
207  return true;
208  }
209  else
210  {
211  return false;
212  }
213 }
214 
215 template <typename KeyType, typename ValueType>
217 MinHeap<KeyType, ValueType>::Insert(KeyType const& key, ValueType const& value)
218 {
219  // Return immediately when the heap is full.
220  if (mNumElements == static_cast<int>(mRecords.size()))
221  {
222  return nullptr;
223  }
224 
225  // Store the input information in the last heap record, which is the last
226  // leaf in the tree.
227  int child = mNumElements++;
228  Record * record = mPointers[child];
229  record->key = key;
230  record->value = value;
231 
232  // Propagate the information toward the root of the tree until it reaches
233  // its correct position, thus restoring the tree to a valid heap.
234  while (child > 0)
235  {
236  int parent = (child - 1) / 2;
237  if (mPointers[parent]->value <= value)
238  {
239  // The parent has a value smaller than or equal to the child's
240  // value, so we now have a valid heap.
241  break;
242  }
243 
244  // The parent has a larger value than the child's value. Swap the
245  // parent and child:
246 
247  // Move the parent into the child's slot.
248  mPointers[child] = mPointers[parent];
249  mPointers[child]->index = child;
250 
251  // Move the child into the parent's slot.
252  mPointers[parent] = record;
253  mPointers[parent]->index = parent;
254 
255  child = parent;
256  }
257 
258  return mPointers[child];
259 }
260 
261 template <typename KeyType, typename ValueType>
263 {
264  // Return immediately when the heap is empty.
265  if (mNumElements == 0)
266  {
267  return false;
268  }
269 
270  // Get the information from the root of the heap.
271  Record* root = mPointers[0];
272  key = root->key;
273  value = root->value;
274 
275  // Restore the tree to a heap. Abstractly, record is the new root of
276  // the heap. It is moved down the tree via parent-child swaps until it
277  // is in a location that restores the tree to a heap.
278  int last = --mNumElements;
279  Record* record = mPointers[last];
280  int parent = 0, child = 1;
281  while (child <= last)
282  {
283  if (child < last)
284  {
285  // Select the child with smallest value to be the one that is
286  // swapped with the parent, if necessary.
287  int childP1 = child + 1;
288  if (mPointers[childP1]->value < mPointers[child]->value)
289  {
290  child = childP1;
291  }
292  }
293 
294  if (record->value <= mPointers[child]->value)
295  {
296  // The tree is now a heap.
297  break;
298  }
299 
300  // Move the child into the parent's slot.
301  mPointers[parent] = mPointers[child];
302  mPointers[parent]->index = parent;
303 
304  parent = child;
305  child = 2 * child + 1;
306  }
307 
308  // The previous 'last' record was moved to the root and propagated down
309  // the tree to its final resting place, restoring the tree to a heap.
310  // The slot mPointers[parent] is that resting place.
311  mPointers[parent] = record;
312  mPointers[parent]->index = parent;
313 
314  // The old root record must not be lost. Attach it to the slot that
315  // contained the old last record.
316  mPointers[last] = root;
317  mPointers[last]->index = last;
318  return true;
319 }
320 
321 template <typename KeyType, typename ValueType>
322 void MinHeap<KeyType, ValueType>::Update(Record* record, ValueType const& value)
323 {
324  // Return immediately on invalid record.
325  if (!record)
326  {
327  return;
328  }
329 
330  int parent, child, childP1, maxChild;
331 
332  if (record->value < value)
333  {
334  record->value = value;
335 
336  // The new value is larger than the old value. Propagate it toward
337  // the leaves.
338  parent = record->index;
339  child = 2 * parent + 1;
340  while (child < mNumElements)
341  {
342  // At least one child exists. Locate the one of maximum value.
343  childP1 = child + 1;
344  if (childP1 < mNumElements)
345  {
346  // Two children exist.
347  if (mPointers[child]->value <= mPointers[childP1]->value)
348  {
349  maxChild = child;
350  }
351  else
352  {
353  maxChild = childP1;
354  }
355  }
356  else
357  {
358  // One child exists.
359  maxChild = child;
360  }
361 
362  if (value <= mPointers[maxChild]->value)
363  {
364  // The new value is in the correct place to restore the tree
365  // to a heap.
366  break;
367  }
368 
369  // The child has a larger value than the parent's value. Swap
370  // the parent and child:
371 
372  // Move the child into the parent's slot.
373  mPointers[parent] = mPointers[maxChild];
374  mPointers[parent]->index = parent;
375 
376  // Move the parent into the child's slot.
377  mPointers[maxChild] = record;
378  mPointers[maxChild]->index = maxChild;
379 
380  parent = maxChild;
381  child = 2 * parent + 1;
382  }
383  }
384  else if (value < record->value)
385  {
386  record->value = value;
387 
388  // The new weight is smaller than the old weight. Propagate it
389  // toward the root.
390  child = record->index;
391  while (child > 0)
392  {
393  // A parent exists.
394  parent = (child - 1) / 2;
395 
396  if (mPointers[parent]->value <= value)
397  {
398  // The new value is in the correct place to restore the tree
399  // to a heap.
400  break;
401  }
402 
403  // The parent has a smaller value than the child's value. Swap
404  // the child and parent:
405 
406  // Move the parent into the child's slot.
407  mPointers[child] = mPointers[parent];
408  mPointers[child]->index = child;
409 
410  // Move the child into the parent's slot.
411  mPointers[parent] = record;
412  mPointers[parent]->index = parent;
413 
414  child = parent;
415  }
416  }
417 }
418 
419 template <typename KeyType, typename ValueType>
421 {
422  for (int child = 0; child < mNumElements; ++child)
423  {
424  int parent = (child - 1) / 2;
425  if (parent > 0)
426  {
427  if (mPointers[child]->value < mPointers[parent]->value)
428  {
429  return false;
430  }
431 
432  if (mPointers[parent]->index != parent)
433  {
434  return false;
435  }
436  }
437  }
438 
439  return true;
440 }
441 
442 }
MinHeap(MinHeap const &minHeap)
Definition: GteMinHeap.h:155
MinHeap & operator=(MinHeap const &minHeap)
Definition: GteMinHeap.h:161
Record * Insert(KeyType const &key, ValueType const &value)
Definition: GteMinHeap.h:217
std::vector< Record * > mPointers
Definition: GteMinHeap.h:144
int GetNumElements() const
Definition: GteMinHeap.h:195
GLsizei const GLfloat * value
Definition: glcorearb.h:819
std::vector< Record > mRecords
Definition: GteMinHeap.h:143
void Update(Record *record, ValueType const &value)
Definition: GteMinHeap.h:322
void Reset(int maxElements)
Definition: GteMinHeap.h:174
bool IsValid() const
Definition: GteMinHeap.h:420
bool Remove(KeyType &key, ValueType &value)
Definition: GteMinHeap.h:262
int mNumElements
Definition: GteMinHeap.h:142
GLuint index
Definition: glcorearb.h:781
bool GetMinimum(KeyType &key, ValueType &value) const
Definition: GteMinHeap.h:201


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01