MeshLib C++ Docs
Loading...
Searching...
No Matches
MRHeap.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMacros.h"
4#include "MRVector.h"
5#include "MRTimer.h"
6#include <functional>
7#include <algorithm>
8
9namespace MR
10{
11
14
21template <typename T, typename I, typename P = std::less<T>>
22class Heap
23{
24public:
25 struct Element
26 {
27 I id;
28 T val;
29 };
30
32 explicit Heap( size_t size, T def MR_LIFETIMEBOUND_NESTED = {}, P pred = {} );
34 explicit Heap( std::vector<Element> elms MR_LIFETIMEBOUND_NESTED, P pred = {} );
36 size_t size() const { return heap_.size(); }
38 void resize( size_t size, T def MR_LIFETIME_CAPTURE_BY_NESTED(this) = {} );
40 const T & value( I elemId ) const MR_LIFETIMEBOUND { return heap_[ id2PosInHeap_[ elemId ] ].val; }
42 const Element & top() const MR_LIFETIMEBOUND { return heap_[0]; }
44 void setValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
46 void setLargerValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
47 void setSmallerValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
48 template<typename U>
49 void increaseValue( I elemId, const U & inc ) { setLargerValue( elemId, value( elemId ) + inc ); }
51 Element setTopValue( const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) ) { Element res = top(); setValue( res.id, newVal ); return res; }
52
53private:
55 bool less_( size_t posA, size_t posB ) const;
57 void lift_( size_t pos, I elemId );
58
59private:
60 std::vector<Element> heap_;
61 Vector<size_t, I> id2PosInHeap_;
62 P pred_;
63};
64
65template <typename T, typename I, typename P>
66Heap<T, I, P>::Heap( size_t size, T def, P pred )
67 : heap_( size, { I(), def } )
68 , id2PosInHeap_( size )
69 , pred_( pred )
70{
72 for ( I i{ size_t( 0 ) }; i < size; ++i )
73 {
74 heap_[i].id = i;
75 id2PosInHeap_[i] = i;
76 }
77}
78
79template <typename T, typename I, typename P>
80Heap<T, I, P>::Heap( std::vector<Element> elms, P pred )
81 : heap_( std::move( elms ) )
82 , id2PosInHeap_( heap_.size() )
83 , pred_( pred )
84{
86 std::make_heap( heap_.begin(), heap_.end(), [this]( const Element & a, const Element & b )
87 {
88 if ( pred_( a.val, b.val ) )
89 return true;
90 if ( pred_( b.val, a.val ) )
91 return false;
92 return a.id < b.id;
93 }
94 );
95 for ( size_t i = 0; i < heap_.size(); ++i )
96 id2PosInHeap_[heap_[i].id] = i;
97}
98
99template <typename T, typename I, typename P>
100void Heap<T, I, P>::resize( size_t size, T def )
101{
102 MR_TIMER;
103 assert ( heap_.size() == id2PosInHeap_.size() );
104 while ( heap_.size() < size )
105 {
106 I i( heap_.size() );
107 heap_.push_back( { i, def } );
108 id2PosInHeap_.push_back( i );
109 lift_( i, i );
110 }
111 assert ( heap_.size() == id2PosInHeap_.size() );
112}
113
114template <typename T, typename I, typename P>
115void Heap<T, I, P>::setValue( I elemId, const T & newVal )
116{
117 size_t pos = id2PosInHeap_[ elemId ];
118 assert( heap_[pos].id == elemId );
119 if ( pred_( newVal, heap_[pos].val ) )
120 setSmallerValue( elemId, newVal );
121 else if ( pred_( heap_[pos].val, newVal ) )
122 setLargerValue( elemId, newVal );
123}
124
125template <typename T, typename I, typename P>
126void Heap<T, I, P>::setLargerValue( I elemId, const T & newVal )
127{
128 size_t pos = id2PosInHeap_[ elemId ];
129 assert( heap_[pos].id == elemId );
130 assert( !( pred_( newVal, heap_[pos].val ) ) );
131 heap_[pos].val = newVal;
132 lift_( pos, elemId );
133}
134
135template <typename T, typename I, typename P>
136void Heap<T, I, P>::lift_( size_t pos, I elemId )
137{
138 while ( pos > 0 )
139 {
140 size_t parentPos = ( pos - 1 ) / 2;
141 if ( !( less_( parentPos, pos ) ) )
142 break;
143 auto parentId = heap_[parentPos].id;
144 assert( id2PosInHeap_[parentId] == parentPos );
145 std::swap( heap_[parentPos], heap_[pos] );
146 std::swap( parentPos, pos );
147 id2PosInHeap_[parentId] = parentPos;
148 }
149 id2PosInHeap_[elemId] = pos;
150}
151
152template <typename T, typename I, typename P>
153void Heap<T, I, P>::setSmallerValue( I elemId, const T & newVal )
154{
155 size_t pos = id2PosInHeap_[ elemId ];
156 assert( heap_[pos].id == elemId );
157 assert( !( pred_( heap_[pos].val, newVal ) ) );
158 heap_[pos].val = newVal;
159 for (;;)
160 {
161 size_t child1Pos = 2 * pos + 1;
162 if ( child1Pos >= heap_.size() )
163 break;
164 auto child1Id = heap_[child1Pos].id;
165 size_t child2Pos = 2 * pos + 2;
166 if ( child2Pos >= heap_.size() )
167 {
168 assert( id2PosInHeap_[child1Id] == child1Pos );
169 if ( !( less_( child1Pos, pos ) ) )
170 {
171 std::swap( heap_[child1Pos], heap_[pos] );
172 std::swap( child1Pos, pos );
173 id2PosInHeap_[child1Id] = child1Pos;
174 }
175 break;
176 }
177 auto child2Id = heap_[child2Pos].id;
178 if ( !( less_( child1Pos, pos ) ) && !( less_( child1Pos, child2Pos ) ) )
179 {
180 std::swap( heap_[child1Pos], heap_[pos] );
181 std::swap( child1Pos, pos );
182 id2PosInHeap_[child1Id] = child1Pos;
183 }
184 else if ( !( less_( child2Pos, pos ) ) )
185 {
186 assert( !( less_( child2Pos, child1Pos ) ) );
187 std::swap( heap_[child2Pos], heap_[pos] );
188 std::swap( child2Pos, pos );
189 id2PosInHeap_[child2Id] = child2Pos;
190 }
191 else
192 {
193 assert( !( less_( pos, child1Pos ) ) );
194 assert( !( less_( pos, child2Pos ) ) );
195 break;
196 }
197 }
198 id2PosInHeap_[elemId] = pos;
199}
200
201template <typename T, typename I, typename P>
202inline bool Heap<T, I, P>::less_( size_t posA, size_t posB ) const
203{
204 const auto & a = heap_[posA];
205 const auto & b = heap_[posB];
206 if ( pred_( a.val, b.val ) )
207 return true;
208 if ( pred_( b.val, a.val ) )
209 return false;
210 return a.id < b.id;
211}
212
214
215}
#define MR_LIFETIMEBOUND
Definition MRMacros.h:81
#define MR_LIFETIME_CAPTURE_BY_NESTED(x)
Definition MRMacros.h:86
#define MR_LIFETIMEBOUND_NESTED
Definition MRMacros.h:84
#define MR_TIMER
namespace MR
Definition MRTimer.h:56
stores map from element id in[0, size) to T;
Definition MRHeap.h:23
const Element & top() const MR_LIFETIMEBOUND
returns the element with the largest value
Definition MRHeap.h:42
size_t size() const
returns the size of the heap
Definition MRHeap.h:36
const T & value(I elemId) const MR_LIFETIMEBOUND
returns the value associated with given element
Definition MRHeap.h:40
Element setTopValue(const T &newVal MR_LIFETIME_CAPTURE_BY_NESTED(this))
sets new value to the current top element, returning its previous value
Definition MRHeap.h:51
void increaseValue(I elemId, const U &inc)
Definition MRHeap.h:49
std::vector<T>-like container that requires specific indexing type,
Definition MRVector.h:23
void setValue(I elemId, const T &newVal MR_LIFETIME_CAPTURE_BY_NESTED(this))
sets new value to given element
Definition MRHeap.h:115
void resize(size_t size, T def MR_LIFETIME_CAPTURE_BY_NESTED(this)={})
increases the size of the heap by adding elements at the end
Definition MRHeap.h:100
void setSmallerValue(I elemId, const T &newVal MR_LIFETIME_CAPTURE_BY_NESTED(this))
Definition MRHeap.h:153
void setLargerValue(I elemId, const T &newVal MR_LIFETIME_CAPTURE_BY_NESTED(this))
sets new value to given element, which shall be larger/smaller than the current value
Definition MRHeap.h:126
Heap(size_t size, T def MR_LIFETIMEBOUND_NESTED={}, P pred={})
constructs heap for given number of elements, assigning given default value to each element
Definition MRHeap.h:66
ImVec2 size(const ViewportRectangle &rect)
Definition MRViewport.h:32
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRHeap.h:26
T val
Definition MRHeap.h:28
I id
Definition MRHeap.h:27