ITK  6.0.0
Insight Toolkit
itkPriorityQueueContainer.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkPriorityQueueContainer_h
19#define itkPriorityQueueContainer_h
20
21#include "itkVectorContainer.h"
22#include "itkIntTypes.h"
23#include "itkNumericTraits.h"
24
25#include <functional>
26#include <queue>
27#include <vector>
28
29namespace itk
30{
31// first define a common interface all the wrapper will have to abide to
32// this will let us define our own wrapper with different behavior.
33// As an example we define below a wrapper for a min sorted or max sorted
34// queue.
35template <typename TElement, typename TElementIdentifier = IdentifierType>
36class ITK_TEMPLATE_EXPORT ElementWrapperInterface
37{
38public:
39 using ElementType = TElement;
40 using ElementIdentifierType = TElementIdentifier;
41
43
45 virtual ~ElementWrapperInterface() = default;
46
48 GetLocation(const ElementType & element) const = 0;
49
50 virtual void
51 SetLocation(ElementType & element, const ElementIdentifierType & identifier) = 0;
52
53 virtual bool
54 is_less(const ElementType & element1, const ElementType & element2) const = 0;
55
56 virtual bool
57 is_greater(const ElementType & element1, const ElementType & element2) const = 0;
58};
59// ------------------------------------------------------------------------
60
61
62// ------------------------------------------------------------------------
63// If you want to manage the items outside the queue for example, if you don't
64// want the queue to manage the items memory, then you can use this wrapper
65// around pointers to items. It follows the ElementWrapperInterface and thus
66// can be used in the queue.
67//
68template <typename TElementWrapperPointer, typename TElementIdentifier = IdentifierType>
69class ITK_TEMPLATE_EXPORT ElementWrapperPointerInterface
70{
71public:
72 using ElementWrapperPointerType = TElementWrapperPointer;
73 using ElementIdentifierType = TElementIdentifier;
74
76
79
80 TElementIdentifier
81 GetLocation(const ElementWrapperPointerType & element) const;
82
83 void
85
86 virtual bool
87 is_less(const ElementWrapperPointerType & element1, const ElementWrapperPointerType & element2) const;
88
89 virtual bool
90 is_greater(const ElementWrapperPointerType & element1, const ElementWrapperPointerType & element2) const;
91};
92// ------------------------------------------------------------------------
93
94// ------------------------------------------------------------------------
95// To follow ITK rule, we template the ElementWrapperType priority and the element
96// identifier type.
97// For example, as we want to use this for decimation, the element will be some
98// kind of cell or point pointer, the priority will be whatever you want it to
99// be as long as you define the comparison operators, and the identifier will
100// set according to the size of the vector you want to create.
101//
102// this implementation is used for min sorted priorityqueue
103template <typename TElement, typename TElementPriority = double, typename TElementIdentifier = IdentifierType>
104class ITK_TEMPLATE_EXPORT MinPriorityQueueElementWrapper
105 : public ElementWrapperInterface<MinPriorityQueueElementWrapper<TElement, TElementPriority, TElementIdentifier>,
106 TElementIdentifier>
107{
108public:
110 using ElementType = TElement;
111 using ElementPriorityType = TElementPriority;
112 using ElementIdentifierType = TElementIdentifier;
113
114 ElementType m_Element{};
116 ElementIdentifierType m_Location{ Superclass::m_ElementNotFound };
117
119
121
123
124 bool
126
127 bool
128 operator<(const MinPriorityQueueElementWrapper & other) const;
129
130 bool
132
134 GetLocation(const MinPriorityQueueElementWrapper & element) const override;
135
136 void
137 SetLocation(MinPriorityQueueElementWrapper & element, const ElementIdentifierType & identifier) override;
138
139 // still virtual to be able to overload it in the Max flavor
140 bool
142 const MinPriorityQueueElementWrapper & element2) const override;
143
144 bool
146 const MinPriorityQueueElementWrapper & element2) const override;
147};
148// ------------------------------------------------------------------------
149
150
151// ------------------------------------------------------------------------
152// this implementation is used for max sorted priorityqueue
153// most of the job is already done, just need to overload the less
154// and greater ops.
155template <typename TElement, typename TElementPriority = double, typename TElementIdentifier = IdentifierType>
156class ITK_TEMPLATE_EXPORT MaxPriorityQueueElementWrapper
157 : public MinPriorityQueueElementWrapper<TElement, TElementPriority, TElementIdentifier>
158{
159public:
160 using ElementType = TElement;
161 using ElementPriorityType = TElementPriority;
162 using ElementIdentifierType = TElementIdentifier;
163
166
168
170
171 virtual bool
173
174 bool
175 is_less(const Superclass & element1, const Superclass & element2) const override;
176
177 virtual bool
179
180 bool
181 is_greater(const Superclass & element1, const Superclass & element2) const override;
182};
183// ------------------------------------------------------------------------
184
185
186// ------------------------------------------------------------------------
187// finally, implement the priority queue itself on top of an
188// itk::VectorContainer
189template <typename TElementWrapper,
190 typename TElementWrapperInterface,
191 typename TElementPriority = double,
192 typename TElementIdentifier = IdentifierType>
193class ITK_TEMPLATE_EXPORT PriorityQueueContainer : public VectorContainer<TElementIdentifier, TElementWrapper>
194{
195public:
200
201 using ElementIdentifierType = TElementIdentifier;
202 using ElementWrapperType = TElementWrapper;
203 using ElementInterfaceType = TElementWrapperInterface;
204
206
207public:
209 ~PriorityQueueContainer() override = default;
210
211 template <typename TInputIterator>
212 PriorityQueueContainer(TInputIterator first, TInputIterator last)
213 : Superclass()
214 {
215 TInputIterator it = first;
216 while (it != last)
217 {
218 this->Push(*it);
219 ++it;
220 }
221 }
222
223public:
224 itkNewMacro(Self);
225 itkOverrideGetNameOfClassMacro(PriorityQueueContainer);
226
227 // void Reserve( ElementIdentifier NbOfElementsToStore )
228 //{ this->Superclass->Reserve( NbOfElementsToStore ); }
229 // void Squeeze( ) { this->Superclass->Squeeze( ); }
230 void
232 bool
233 Empty() const;
234 void
236
237 const ElementWrapperType &
238 Peek() const;
239
240 void
242
246 bool
247 Update(const ElementWrapperType & element);
248
252 bool
254
255protected:
256 // One instance of the interface to deal with the functions calls
257 ElementInterfaceType m_Interface{};
258
259 inline ElementWrapperType &
261 {
262 return this->operator[](identifier);
263 }
264
265 inline const ElementWrapperType &
267 {
268 return this->operator[](identifier);
269 }
270
271 inline void
273 {
274 this->operator[](identifier) = element;
275 m_Interface.SetLocation(element, identifier);
276 }
277
278 inline ElementIdentifierType
279 GetParent(const ElementIdentifierType & identifier) const
280 {
281 return ((identifier - 1) >> 1);
282 }
283
284 inline ElementIdentifierType
285 GetLeft(const ElementIdentifierType & identifier) const
286 {
287 return ((identifier << 1) + 1);
288 }
289
290 inline ElementIdentifierType
291 GetRight(const ElementIdentifierType & identifier) const
292 {
293 return ((identifier << 1) + 2);
294 }
295
296 inline bool
298 {
299 return (iId > 0);
300 }
301
302 void
304
305
306 void
308};
309// ------------------------------------------------------------------------
310
311} // namespace itk
312
313#include "itkPriorityQueueContainer.hxx"
314#endif
static const ElementIdentifierType m_ElementNotFound
virtual bool is_greater(const ElementType &element1, const ElementType &element2) const =0
virtual ~ElementWrapperInterface()=default
virtual void SetLocation(ElementType &element, const ElementIdentifierType &identifier)=0
virtual bool is_less(const ElementType &element1, const ElementType &element2) const =0
virtual ElementIdentifierType GetLocation(const ElementType &element) const =0
virtual ~ElementWrapperPointerInterface()=default
virtual bool is_less(const ElementWrapperPointerType &element1, const ElementWrapperPointerType &element2) const
void SetLocation(ElementWrapperPointerType &element, const ElementIdentifierType &identifier)
TElementIdentifier GetLocation(const ElementWrapperPointerType &element) const
virtual bool is_greater(const ElementWrapperPointerType &element1, const ElementWrapperPointerType &element2) const
static const ElementIdentifierType m_ElementNotFound
Light weight base class for most itk classes.
bool is_greater(const Superclass &element1, const Superclass &element2) const override
bool is_less(const Superclass &element1, const Superclass &element2) const override
MaxPriorityQueueElementWrapper(ElementType element, ElementPriorityType priority)
virtual bool is_greater(const MaxPriorityQueueElementWrapper &element1, const MaxPriorityQueueElementWrapper &element2) const
~MaxPriorityQueueElementWrapper() override=default
virtual bool is_less(const MaxPriorityQueueElementWrapper &element1, const MaxPriorityQueueElementWrapper &element2) const
bool is_greater(const MinPriorityQueueElementWrapper &element1, const MinPriorityQueueElementWrapper &element2) const override
bool operator>(const MinPriorityQueueElementWrapper &other) const
bool operator==(const MinPriorityQueueElementWrapper &other) const
bool is_less(const MinPriorityQueueElementWrapper &element1, const MinPriorityQueueElementWrapper &element2) const override
ElementIdentifierType GetLocation(const MinPriorityQueueElementWrapper &element) const override
void SetLocation(MinPriorityQueueElementWrapper &element, const ElementIdentifierType &identifier) override
~MinPriorityQueueElementWrapper() override=default
MinPriorityQueueElementWrapper(ElementType element, ElementPriorityType priority)
ElementWrapperType & GetElementAtLocation(const ElementIdentifierType &identifier)
void UpdateDownTree(const ElementIdentifierType &identifier)
TElementWrapperInterface ElementInterfaceType
ElementIdentifierType GetParent(const ElementIdentifierType &identifier) const
bool HasParent(const ElementIdentifierType &iId) const
bool DeleteElement(const ElementWrapperType &element)
void UpdateUpTree(const ElementIdentifierType &identifier)
ElementIdentifierType GetRight(const ElementIdentifierType &identifier) const
bool Update(const ElementWrapperType &element)
~PriorityQueueContainer() override=default
void SetElementAtLocation(const ElementIdentifierType &identifier, ElementWrapperType &element)
static const ElementIdentifierType m_ElementNotFound
const ElementWrapperType & Peek() const
ElementIdentifierType GetLeft(const ElementIdentifierType &identifier) const
void Push(ElementWrapperType element)
PriorityQueueContainer(TInputIterator first, TInputIterator last)
const ElementWrapperType & GetElementAtLocation(const ElementIdentifierType &identifier) const
Define a front-end to the STL "vector" container that conforms to the IndexedContainerInterface.
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
SizeValueType IdentifierType
Definition: itkIntTypes.h:90
bool operator<(const Index< VDimension > &one, const Index< VDimension > &two)
Definition: itkIndex.h:557