mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
125 lines
2.5 KiB
C++
125 lines
2.5 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
|