deargui-vpl/applications/nodehub/core/XPriorityQueue.h
2026-02-03 18:25:25 +01:00

177 lines
3.8 KiB
C++

#ifndef XPRIORITYQUEUE_H
#define XPRIORITYQUEUE_H
template <class T>
struct XPriority
{
int operator()(const T& iT) const {
return iT;
}
};
/************************************************
Name: XPriorityQueue
Summary: Class representation of a priority queue.
Template Parameters:
T : type of object to store into the queue
PF : priority function, which is use to tell the priority (an int)
of a T object.
Remarks:
This container is used to fastly pop an object, sorted by a criterion, called here the
priority of the object. Insertion and Pop are in O(log(n)) and the objects are stored
flat, in an array, avoiding many small allocations.
You can not store objects with ctor and dtor in it because they won't be called.
See Also : XArray, XList
************************************************/
template <class T, class PF = XPriority<T> >
class XPriorityQueue
{
public:
/************************************************
Summary: Constructors.
Input Arguments:
iBaseNumber: Default number of reserved elements.
************************************************/
XPriorityQueue(int iBaseNumber = 0):m_Cells(iBaseNumber) {}
/************************************************
Summary: Removes all the elements from the queue.
Remarks:
The memory allocated is not freed by this call.
************************************************/
void Clear()
{
if (m_Cells.Size()) { // already allocated : sets to the beginning
m_Cells.Resize(1);
}
}
void Insert(const T& iT)
{
if (!m_Cells.Size()) { // first insertion : init
m_Cells.Reserve(2);
m_Cells.Resize(1); // the first node is the root
}
int i = m_Cells.Size();
m_Cells.PushBack(iT);
T* cells = m_Cells.Begin();
PF prio;
int insertPrio = prio(iT);
while (i > 1 && prio(cells[i / 2]) < insertPrio) {
cells[i] = cells[i / 2];
i /= 2;
}
cells[i] = iT;
}
/************************************************
Summary: Removes the higher priority element of
the queue.
Input Arguments:
oT: pointer to the T object that will be filled
with the higher priority element.
The pointer need to be valid.
Return Value: TRUE if an object is popped.
************************************************/
XBOOL
Pop(T* oT)
{
if (m_Cells.Size() <= 1)
return 0;
{
T* cells = m_Cells.Begin();
*oT = cells[1];
}
T tmp = m_Cells.PopBack();
int size = m_Cells.Size();
if (size == 1) // was the last one
return 1;
int i = 1;
int j;
PF prio;
int lastPriority = prio(tmp);
T* cells = m_Cells.Begin();
while (i <= size / 2) {
j = 2 * i;
if (j < size &&
prio(cells[j]) < prio(cells[j + 1])) {
j++;
}
if (prio(cells[j]) <= lastPriority) {
break;
}
cells[i] = cells[j];
i = j;
}
cells[i] = tmp;
return 1;
}
/************************************************
Summary: Peeks the higher priority element of
the queue.
Input Arguments:
oT: pointer to the T object that will be filled
with the higher priority element.
The pointer need to be valid.
Return Value: TRUE if an object is popped.
************************************************/
XBOOL
Peek(T* oT) const
{
if (m_Cells.Size() <= 1)
return 0;
T* cells = m_Cells.Begin();
*oT = cells[1];
return 1;
}
/************************************************
Summary: Returns the occupied size in memory in bytes
Parameters:
addstatic: TRUE if you want to add the size occupied
by the class itself.
************************************************/
int GetMemoryOccupation(XBOOL iAddStatic = FALSE) const
{
return m_Cells.GetMemoryOccupation(iAddStatic);
}
protected:
// array of queue cells
XArray<T> m_Cells;
};
#endif