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