// See the file "COPYING" in the main distribution directory for copyright. #include "zeek/PriorityQueue.h" #include "zeek/zeek-config.h" #include #include #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