UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
IndexPriorityQueue.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "MathUtil.h"
7
8namespace UE
9{
10namespace Geometry
11{
12
22{
23public:
25 bool EnableDebugChecks = false;
26
28 {
29 int id = -1; // external id
30
31 float priority; // the priority of this id
32 int index; // index in tree data structure (tree is stored as flat array)
33 };
34
41
42
47 {
48 Initialize(0);
49 }
50
59
60
68 {
69 nodes.Clear();
71 num_nodes = 0;
72 }
73
74
79 void Clear(bool bFreeMemory = true)
80 {
81 check(bFreeMemory); // not sure exactly how to implement bFreeMemory=false w/ classes below...
82 nodes.Clear();
84 num_nodes = 0;
85 }
86
88 int GetCount() const
89 {
90 return num_nodes;
91 }
92
94 int GetFirstNodeID() const
95 {
96 return nodes[1].id;
97 }
98
101 {
102 return nodes[1].priority;
103 }
104
106 bool Contains(int NodeID) const
107 {
108 if (NodeID > id_to_index.Num() + 1)
109 return false;
110
111 int NodeIndex = id_to_index[NodeID];
113 return false;
114 return nodes[NodeIndex].index > 0;
115 }
116
117
121 void Insert(int NodeID, float priority)
122 {
124 {
125 check(Contains(NodeID) == false);
126 }
127
128 FQueueNode node;
129 node.id = NodeID;
130 node.priority = priority;
131 num_nodes++;
132 node.index = num_nodes;
133 id_to_index[NodeID] = node.index;
134 nodes.InsertAt(node, num_nodes);
135 move_up(nodes[num_nodes].index);
136 }
137
143 {
145 {
146 check(GetCount() > 0);
147 }
148
149 int NodeID = nodes[1].id;
150 remove_at_index(1);
151 return NodeID;
152 }
153
157 void Remove(int NodeID)
158 {
160 {
161 check(Contains(NodeID) == true);
162 }
163
164 int NodeIndex = id_to_index[NodeID];
165 remove_at_index(NodeIndex);
166 }
167
168
172 void Update(int NodeID, float Priority)
173 {
175 {
176 check(Contains(NodeID) == true);
177 }
178
179 int NodeIndex = id_to_index[NodeID];
180
181 FQueueNode n = nodes[NodeIndex];
182 n.priority = Priority;
183 nodes[NodeIndex] = n;
184
185 on_node_updated(NodeIndex);
186 }
187
188
193 float GetPriority(int id)
194 {
196 {
197 check(Contains(id) == true);
198 }
199
200 int iNode = id_to_index[id];
201 return nodes[iNode].priority;
202 }
203
204
205 /*
206 * Internals
207 */
208private:
209
211 void remove_at_index(int NodeIndex)
212 {
213 // node-is-last-node case
214 if (NodeIndex == num_nodes)
215 {
216
217 // null id_to_index entry for the node we remove.
218 int id = nodes[num_nodes].id;
219 id_to_index[id] = -1;
220
221 nodes[num_nodes] = FQueueNode();
222 num_nodes--;
223 return;
224 }
225
226 // TODO: is there a better way to do this? seems random to move the last node to
227 // top of tree? But I guess otherwise we might have to shift entire branches??
228
229 //Swap the node with the last node
230 swap_nodes_at_indices(NodeIndex, num_nodes);
231 // after swap, NodeIndex is the one we want to keep, and numNodes is the one we discard
232 {
233 int id = nodes[num_nodes].id;
234 id_to_index[id] = -1;
235
236 nodes[num_nodes] = FQueueNode();
237 num_nodes--;
238 }
239
240 //Now shift iNode (ie the former last node) up or down as appropriate
241 on_node_updated(NodeIndex);
242 }
243
244
246 void swap_nodes_at_indices(int i1, int i2)
247 {
248 FQueueNode n1 = nodes[i1];
249 n1.index = i2;
250 FQueueNode n2 = nodes[i2];
251 n2.index = i1;
252 nodes[i1] = n2;
253 nodes[i2] = n1;
254
255 id_to_index[n2.id] = i1;
256 id_to_index[n1.id] = i2;
257 }
258
260 void move(int iFrom, int iTo)
261 {
262 FQueueNode n = nodes[iFrom];
263 n.index = iTo;
264 nodes[iTo] = n;
265 id_to_index[n.id] = iTo;
266 }
267
269 void set(int iTo, FQueueNode& n)
270 {
271 n.index = iTo;
272 nodes[iTo] = n;
273 id_to_index[n.id] = iTo;
274 }
275
276
278 void move_up(int iNode)
279 {
280 // save start node, we will move this one to correct position in tree
281 int iStart = iNode;
282 FQueueNode iStartNode = nodes[iStart];
283
284 // while our priority is lower than parent, we swap upwards, ie move parent down
285 int iParent = iNode / 2;
286 while (iParent >= 1)
287 {
288 if (nodes[iParent].priority < iStartNode.priority)
289 {
290 break;
291 }
292 move(iParent, iNode);
293 iNode = iParent;
294 iParent = nodes[iNode].index / 2;
295 }
296
297 // write input node into final position, if we moved it
298 if (iNode != iStart)
299 {
300 set(iNode, iStartNode);
301 }
302 }
303
304
306 void move_down(int iNode)
307 {
308 // save start node, we will move this one to correct position in tree
309 int iStart = iNode;
310 FQueueNode iStartNode = nodes[iStart];
311
312 // keep moving down until lower nodes have higher priority
313 while (true)
314 {
315 int iMoveTo = iNode;
316 int iLeftChild = 2 * iNode;
317
318 // past end of tree, must be in the right spot
319 if (iLeftChild > num_nodes)
320 {
321 break;
322 }
323
324 // check if priority is larger than either child - if so we want to swap
325 float min_priority = iStartNode.priority;
326 float left_child_priority = nodes[iLeftChild].priority;
328 {
331 }
332 int iRightChild = iLeftChild + 1;
333 if (iRightChild <= num_nodes)
334 {
335 if (nodes[iRightChild].priority < min_priority)
336 {
338 }
339 }
340
341 // if we found node with higher priority, swap with it (ie move it up) and take its place
342 // (but we only write start node to final position, not intermediary slots)
343 if (iMoveTo != iNode)
344 {
345 move(iMoveTo, iNode);
346 iNode = iMoveTo;
347 }
348 else
349 {
350 break;
351 }
352 }
353
354 // if we moved node, write it to its new position
355 if (iNode != iStart)
356 {
357 set(iNode, iStartNode);
358 }
359 }
360
361
363 void on_node_updated(int iNode)
364 {
365 int iParent = iNode / 2;
366 if (iParent > 0 && has_higher_priority(iNode, iParent))
367 move_up(iNode);
368 else
369 move_down(iNode);
370 }
371
372
374 bool has_higher_priority(int iHigher, int iLower) const
375 {
376 return (nodes[iHigher].priority < nodes[iLower].priority);
377 }
378
379
380
381
382public:
386 bool IsValidQueue() const
387 {
388 for (int i = 1; i < num_nodes; i++) {
389 int childLeftIndex = 2 * i;
390 if (childLeftIndex < num_nodes && has_higher_priority(childLeftIndex, i))
391 return false;
392
394 if (childRightIndex < num_nodes && has_higher_priority(childRightIndex, i))
395 return false;
396 }
397 return true;
398 }
399
403 bool CheckIds()
404 {
405 // check that every valid node is correctly found by id_to_index
406 bool bValidNodesInSycn = true;
407 for (int i = 1; i < num_nodes + 1; ++i)
408 {
409 const FQueueNode& n = nodes[i];
410 int id = n.id;
411 int index = n.index;
412
414 bValidNodesInSycn = bValidNodesInSycn && (index == i);
415 }
416
417 // check that id_to_index doesn't believe that none valid nodes exist
418 bool bNoOutOfSyncNodes = true;
419 for (int id = 0; id < id_to_index.Num(); ++id)
420 {
421
422 if (Contains(id))
423 {
424 int index = id_to_index[id];
425 const FQueueNode& n = nodes[index];
427 }
428 }
429
431 }
432
433
434 //void DebugPrint() {
435 // for (int i = 1; i <= num_nodes; ++i)
436 // WriteLine("{0} : p {1} index {2} id {3}", i, nodes[i].priority, nodes[i].index, nodes[i].id);
437 //}
438
439
440};
441
442
443} // end namespace UE::Geometry
444} // end namespace UE
#define check(expr)
Definition AssertionMacros.h:314
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Init(const ElementType &Element, SizeType Number)
Definition Array.h:3043
Definition IndexPriorityQueue.h:22
TArray< int > id_to_index
Definition IndexPriorityQueue.h:40
bool Contains(int NodeID) const
Definition IndexPriorityQueue.h:106
void Remove(int NodeID)
Definition IndexPriorityQueue.h:157
float GetPriority(int id)
Definition IndexPriorityQueue.h:193
int GetFirstNodeID() const
Definition IndexPriorityQueue.h:94
void Clear(bool bFreeMemory=true)
Definition IndexPriorityQueue.h:79
float GetFirstNodePriority() const
Definition IndexPriorityQueue.h:100
int num_nodes
Definition IndexPriorityQueue.h:38
int GetCount() const
Definition IndexPriorityQueue.h:88
FIndexPriorityQueue()
Definition IndexPriorityQueue.h:46
void Insert(int NodeID, float priority)
Definition IndexPriorityQueue.h:121
void Update(int NodeID, float Priority)
Definition IndexPriorityQueue.h:172
bool CheckIds()
Definition IndexPriorityQueue.h:403
void Initialize(int MaxNodeID)
Definition IndexPriorityQueue.h:67
FIndexPriorityQueue(int maxID)
Definition IndexPriorityQueue.h:55
TDynamicVector< FQueueNode > nodes
Definition IndexPriorityQueue.h:36
bool IsValidQueue() const
Definition IndexPriorityQueue.h:386
bool EnableDebugChecks
Definition IndexPriorityQueue.h:25
int Dequeue()
Definition IndexPriorityQueue.h:142
Definition DynamicVector.h:27
Definition AdvancedWidgetsModule.cpp:13
Definition IndexPriorityQueue.h:28
int index
Definition IndexPriorityQueue.h:32
int id
Definition IndexPriorityQueue.h:29
float priority
Definition IndexPriorityQueue.h:31