zeek/src/PriorityQueue.cc

142 lines
2.3 KiB
C++

// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/PriorityQueue.h"
#include "zeek/zeek-config.h"
#include <cstdio>
#include <cstdlib>
#include "zeek/Reporter.h"
#include "zeek/util.h"
namespace zeek::detail
{
PriorityQueue::PriorityQueue(int initial_size) : max_heap_size(initial_size)
{
heap = new PQ_Element*[max_heap_size];
}
PriorityQueue::~PriorityQueue()
{
for ( int i = 0; i < heap_size; ++i )
delete heap[i];
delete[] heap;
}
PQ_Element* PriorityQueue::Remove()
{
if ( heap_size == 0 )
return nullptr;
PQ_Element* top = heap[0];
--heap_size;
SetElement(0, heap[heap_size]);
BubbleDown(0);
top->SetOffset(-1); // = not in heap
return top;
}
PQ_Element* PriorityQueue::Remove(PQ_Element* e)
{
if ( e->Offset() < 0 || e->Offset() >= heap_size || heap[e->Offset()] != e )
return nullptr; // not in heap
e->MinimizeTime();
BubbleUp(e->Offset());
PQ_Element* e2 = Remove();
if ( e != e2 )
reporter->InternalError("inconsistency in PriorityQueue::Remove");
return e2;
}
bool PriorityQueue::Add(PQ_Element* e)
{
SetElement(heap_size, e);
BubbleUp(heap_size);
++cumulative_num;
if ( ++heap_size > peak_heap_size )
peak_heap_size = heap_size;
if ( heap_size >= max_heap_size )
return Resize(max_heap_size * 2);
else
return true;
}
bool PriorityQueue::Resize(int new_size)
{
PQ_Element** tmp = new PQ_Element*[new_size];
for ( int i = 0; i < max_heap_size; ++i )
tmp[i] = heap[i];
delete[] heap;
heap = tmp;
max_heap_size = new_size;
return heap != nullptr;
}
void PriorityQueue::BubbleUp(int bin)
{
if ( bin == 0 )
return;
int p = Parent(bin);
if ( heap[p]->Time() > heap[bin]->Time() )
{
Swap(p, bin);
BubbleUp(p);
}
}
void PriorityQueue::BubbleDown(int bin)
{
double v = heap[bin]->Time();
int l = LeftChild(bin);
int r = RightChild(bin);
if ( l >= heap_size )
return; // No children.
if ( r >= heap_size )
{ // Just a left child.
if ( heap[l]->Time() < v )
Swap(l, bin);
}
else
{
double lv = heap[l]->Time();
double rv = heap[r]->Time();
if ( lv < rv )
{
if ( lv < v )
{
Swap(l, bin);
BubbleDown(l);
}
}
else if ( rv < v )
{
Swap(r, bin);
BubbleDown(r);
}
}
}
} // namespace zeek::detail