summaryrefslogtreecommitdiffstats
path: root/include/ds/PriorityQueue.h
diff options
context:
space:
mode:
authorDouglas Rumbaugh <dbr4@psu.edu>2023-05-08 12:59:46 -0400
committerDouglas Rumbaugh <dbr4@psu.edu>2023-05-08 12:59:46 -0400
commitfdf5ef27fec1368a33801a98bbc5ed3556476979 (patch)
tree7ecd9477fed6495d05a44343e19bfb6480785c7a /include/ds/PriorityQueue.h
parent2380dd4d73cd6a179567e06e1aa4871ad44ccce3 (diff)
downloaddynamic-extension-fdf5ef27fec1368a33801a98bbc5ed3556476979.tar.gz
Began porting source files over from other repository
Diffstat (limited to 'include/ds/PriorityQueue.h')
-rw-r--r--include/ds/PriorityQueue.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/include/ds/PriorityQueue.h b/include/ds/PriorityQueue.h
new file mode 100644
index 0000000..49f3e41
--- /dev/null
+++ b/include/ds/PriorityQueue.h
@@ -0,0 +1,135 @@
+/*
+ * include/ds/PriorityQueue.h
+ *
+ * Copyright (C) 2023 Douglas Rumbaugh <drumbaugh@psu.edu>
+ * Dong Xie <dongx@psu.edu>
+ *
+ * All rights reserved. Published under the Modified BSD License.
+ *
+ */
+#pragma once
+
+#include <vector>
+#include <cassert>
+
+#include "util/record.h"
+
+namespace lsm {
+
+struct queue_record {
+ const char *data;
+ size_t version;
+};
+
+
+class PriorityQueue {
+public:
+ PriorityQueue(size_t size) : data(size), tail(0) {}
+ ~PriorityQueue() = default;
+
+ size_t size() const {
+ return tail;
+ }
+
+ void pop() {
+ assert(this->tail != 0);
+
+ // If there is only one element, just decrement the
+ // tail.
+ if (this->size() == 1) {
+ this->tail--;
+ return;
+ }
+
+ swap(0, --this->tail);
+
+ ssize_t idx = 0;
+ ssize_t child_idx;
+
+ while ((child_idx = min_child(idx)) != -1 && heap_cmp(child_idx, idx)) {
+ swap(idx, child_idx);
+ idx = child_idx;
+ }
+ }
+
+ void push(const char* record, size_t version=0) {
+ assert(tail != this->data.size());
+
+ size_t new_idx = this->tail++;
+ this->data[new_idx] = {record, version};
+
+ while (new_idx != 0 && !heap_cmp(parent(new_idx), new_idx)) {
+ swap(parent(new_idx), new_idx);
+ new_idx = parent(new_idx);
+ }
+ }
+
+
+ queue_record peek(size_t depth=0) {
+ ssize_t idx = 0;
+ size_t cur_depth = 0;
+
+ while (cur_depth != depth) {
+ idx = min_child(idx);
+ assert(idx != -1);
+ cur_depth++;
+ }
+
+ return this->data[idx];
+ }
+
+private:
+ std::vector<queue_record> data;
+ size_t tail;
+
+ /*
+ * Swap the elements at position a and position
+ * b within the heap
+ */
+ inline void swap(size_t a, size_t b) {
+ if (a == b) return;
+
+ queue_record temp = this->data[a];
+ this->data[a] = this->data[b];
+ this->data[b] = temp;
+ }
+
+ inline size_t left_child(size_t idx) {
+ return 2 * idx + 1;
+ }
+
+ inline size_t right_child(size_t idx) {
+ return 2 * idx + 2;
+ }
+
+ inline size_t parent(size_t idx) {
+ return (idx - 1) / 2;
+ }
+
+ inline ssize_t min_child(size_t idx) {
+ ssize_t left = left_child(idx) < tail ? left_child(idx) : -1;
+ ssize_t right = right_child(idx) < tail ? right_child(idx) : -1;
+
+ if (left == -1 && right == -1) {
+ return -1;
+ } else if (left == -1) {
+ return right;
+ } else if (right == -1) {
+ return left;
+ }
+
+ return (heap_cmp(left, right)) ? left : right;
+ }
+
+ inline bool heap_cmp(size_t a, size_t b) {
+ auto cmp = record_cmp(this->data[a].data, this->data[b].data);
+ if (cmp == 0) {
+ if (this->data[a].version != this->data[b].version)
+ return this->data[a].version < this->data[b].version;
+ else return is_tombstone(this->data[a].data) && is_tombstone(this->data[b].data);
+ }
+ return cmp == -1;
+ }
+
+};
+}