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 {
28 T val;
29 };
30
32 Heap( P pred = {} ) : pred_( pred ) {}
33
35 explicit Heap( size_t size, T def MR_LIFETIMEBOUND_NESTED = {}, P pred = {} );
36
38 explicit Heap( std::vector<Element> elms MR_LIFETIMEBOUND_NESTED, P pred = {} );
39
41 size_t size() const { return heap_.size(); }
42
44 void resize( size_t size, T def MR_LIFETIME_CAPTURE_BY_NESTED(this) = {} );
45
47 const T & value( I elemId ) const MR_LIFETIMEBOUND { return heap_[ id2PosInHeap_[ elemId ] ].val; }
48
50 const Element & top() const MR_LIFETIMEBOUND { return heap_[0]; }
51
53 void setValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
54
56 void setLargerValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
57 void setSmallerValue( I elemId, const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) );
58 template<typename U>
59 void increaseValue( I elemId, const U & inc ) { setLargerValue( elemId, value( elemId ) + inc ); }
60
62 Element setTopValue( const T & newVal MR_LIFETIME_CAPTURE_BY_NESTED(this) ) { Element res = top(); setValue( res.id, newVal ); return res; }
63
64private:
66 bool less_( size_t posA, size_t posB ) const;
67
69 void lift_( size_t pos, I elemId );
70
71private:
72 std::vector<Element> heap_;
73 Vector<size_t, I> id2PosInHeap_;
74 P pred_;
75};
76
77template <typename T, typename I, typename P>
78Heap<T, I, P>::Heap( size_t size, T def, P pred )
79 : heap_( size, { I(), def } )
80 , id2PosInHeap_( size )
81 , pred_( pred )
82{
84 for ( I i{ size_t( 0 ) }; i < size; ++i )
85 {
86 heap_[i].id = i;
87 id2PosInHeap_[i] = i;
88 }
89}
90
91template <typename T, typename I, typename P>
92Heap<T, I, P>::Heap( std::vector<Element> elms, P pred )
93 : heap_( std::move( elms ) )
94 , id2PosInHeap_( heap_.size() )
95 , pred_( pred )
96{
98 std::make_heap( heap_.begin(), heap_.end(), [this]( const Element & a, const Element & b )
99 {
100 if ( pred_( a.val, b.val ) )
101 return true;
102 if ( pred_( b.val, a.val ) )
103 return false;
104 return a.id < b.id;
105 }
106 );
107 for ( size_t i = 0; i < heap_.size(); ++i )
108 id2PosInHeap_[heap_[i].id] = i;
109}
110
111template <typename T, typename I, typename P>
112void Heap<T, I, P>::resize( size_t size, T def )
113{
114 MR_TIMER;
115 assert ( heap_.size() == id2PosInHeap_.size() );
116 while ( heap_.size() < size )
117 {
118 I i( heap_.size() );
119 heap_.push_back( { i, def } );
120 id2PosInHeap_.push_back( i );
121 lift_( i, i );
122 }
123 assert ( heap_.size() == id2PosInHeap_.size() );
124}
125
126template <typename T, typename I, typename P>
127void Heap<T, I, P>::setValue( I elemId, const T & newVal )
128{
129 size_t pos = id2PosInHeap_[ elemId ];
130 assert( heap_[pos].id == elemId );
131 if ( pred_( newVal, heap_[pos].val ) )
132 setSmallerValue( elemId, newVal );
133 else if ( pred_( heap_[pos].val, newVal ) )
134 setLargerValue( elemId, newVal );
135}
136
137template <typename T, typename I, typename P>
138void Heap<T, I, P>::setLargerValue( I elemId, const T & newVal )
139{
140 size_t pos = id2PosInHeap_[ elemId ];
141 assert( heap_[pos].id == elemId );
142 assert( !( pred_( newVal, heap_[pos].val ) ) );
143 heap_[pos].val = newVal;
144 lift_( pos, elemId );
145}
146
147template <typename T, typename I, typename P>
148void Heap<T, I, P>::lift_( size_t pos, I elemId )
149{
150 while ( pos > 0 )
151 {
152 size_t parentPos = ( pos - 1 ) / 2;
153 if ( !( less_( parentPos, pos ) ) )
154 break;
155 auto parentId = heap_[parentPos].id;
156 assert( id2PosInHeap_[parentId] == parentPos );
157 std::swap( heap_[parentPos], heap_[pos] );
158 std::swap( parentPos, pos );
159 id2PosInHeap_[parentId] = parentPos;
160 }
161 id2PosInHeap_[elemId] = pos;
162}
163
164template <typename T, typename I, typename P>
165void Heap<T, I, P>::setSmallerValue( I elemId, const T & newVal )
166{
167 size_t pos = id2PosInHeap_[ elemId ];
168 assert( heap_[pos].id == elemId );
169 assert( !( pred_( heap_[pos].val, newVal ) ) );
170 heap_[pos].val = newVal;
171 for (;;)
172 {
173 size_t child1Pos = 2 * pos + 1;
174 if ( child1Pos >= heap_.size() )
175 break;
176 auto child1Id = heap_[child1Pos].id;
177 size_t child2Pos = 2 * pos + 2;
178 if ( child2Pos >= heap_.size() )
179 {
180 assert( id2PosInHeap_[child1Id] == child1Pos );
181 if ( !( less_( child1Pos, pos ) ) )
182 {
183 std::swap( heap_[child1Pos], heap_[pos] );
184 std::swap( child1Pos, pos );
185 id2PosInHeap_[child1Id] = child1Pos;
186 }
187 break;
188 }
189 auto child2Id = heap_[child2Pos].id;
190 if ( !( less_( child1Pos, pos ) ) && !( less_( child1Pos, child2Pos ) ) )
191 {
192 std::swap( heap_[child1Pos], heap_[pos] );
193 std::swap( child1Pos, pos );
194 id2PosInHeap_[child1Id] = child1Pos;
195 }
196 else if ( !( less_( child2Pos, pos ) ) )
197 {
198 assert( !( less_( child2Pos, child1Pos ) ) );
199 std::swap( heap_[child2Pos], heap_[pos] );
200 std::swap( child2Pos, pos );
201 id2PosInHeap_[child2Id] = child2Pos;
202 }
203 else
204 {
205 assert( !( less_( pos, child1Pos ) ) );
206 assert( !( less_( pos, child2Pos ) ) );
207 break;
208 }
209 }
210 id2PosInHeap_[elemId] = pos;
211}
212
213template <typename T, typename I, typename P>
214inline bool Heap<T, I, P>::less_( size_t posA, size_t posB ) const
215{
216 const auto & a = heap_[posA];
217 const auto & b = heap_[posB];
218 if ( pred_( a.val, b.val ) )
219 return true;
220 if ( pred_( b.val, a.val ) )
221 return false;
222 return a.id < b.id;
223}
224
226
227}
#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
FUNCTION in GCC/Clang returns only short function name without class name and template parameters
Definition MRTimer.h:56
const Element & top() const MR_LIFETIMEBOUND
returns the element with the largest value
Definition MRHeap.h:50
size_t size() const
returns the size of the heap
Definition MRHeap.h:41
Heap(P pred={})
constructs an empty heap
Definition MRHeap.h:32
const T & value(I elemId) const MR_LIFETIMEBOUND
returns the value associated with given element
Definition MRHeap.h:47
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:62
void increaseValue(I elemId, const U &inc)
Definition MRHeap.h:59
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:127
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:112
void setSmallerValue(I elemId, const T &newVal MR_LIFETIME_CAPTURE_BY_NESTED(this))
Definition MRHeap.h:165
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:138
ImVec2 size(const ViewportRectangle &rect)
Definition MRViewport.h:32
class MRMESH_CLASS I
Definition MRMeshFwd.h:139
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRHeap.h:26
T val
Definition MRHeap.h:28
I id
Definition MRHeap.h:27