summaryrefslogtreecommitdiffstats
path: root/src/dmclock/support/src/heap.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dmclock/support/src/heap.h247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/dmclock/support/src/heap.h b/src/dmclock/support/src/heap.h
new file mode 100644
index 000000000..6a1f9963a
--- /dev/null
+++ b/src/dmclock/support/src/heap.h
@@ -0,0 +1,247 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+/*
+ * Copyright (C) 2016 Red Hat Inc.
+ *
+ * Author: J. Eric Ivancich <ivancich@redhat.com>
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version
+ * 2.1, as published by the Free Software Foundation. See file
+ * COPYING.
+ */
+
+
+#pragma once
+
+
+#include <vector>
+#include <ostream>
+
+#include "assert.h"
+
+
+namespace crimson {
+
+ /*
+ * T : type of data held in the heap.
+ *
+ * C : class that implements operator() with two arguments and
+ * returns a boolean when the first argument is greater than (higher
+ * in priority than) the second.
+ */
+ template<typename T, typename C>
+ class Heap {
+
+ public:
+
+ class iterator {
+
+ friend Heap<T,C>;
+
+ Heap<T,C>& heap;
+ int index;
+
+ iterator(Heap<T,C>& _heap, int _index) :
+ heap(_heap),
+ index(_index)
+ {
+ // empty
+ }
+
+ public:
+
+ iterator(iterator&& other) :
+ heap(other.heap),
+ index(other.index)
+ {
+ // empty
+ }
+
+ iterator& operator++() {
+ ++index;
+ return *this;
+ }
+
+ bool operator==(const iterator& other) const {
+ return index == other.index;
+ }
+
+ bool operator!=(const iterator& other) const {
+ return !(*this == other);
+ }
+
+ T& operator*() {
+ return heap.data[index];
+ }
+
+ // the item this iterator refers to
+ void increase() {
+ heap.siftUp(index);
+ }
+ }; // class iterator
+
+ friend iterator;
+
+ protected:
+
+ std::vector<T> data;
+ int count;
+ C comparator;
+
+ // parent(0) should be a negative value, which it is due to
+ // truncating towards negative infinity
+ static inline int parent(int i) { return (i - 1) / 2; }
+
+ static inline int lhs(int i) { return 2*i + 1; }
+
+ static inline int rhs(int i) { return 2*i + 2; }
+
+ void siftUp(int i) {
+ assert(i < count);
+
+ while (i > 0) {
+ int pi = parent(i);
+ if (!comparator(data[i], data[pi])) {
+ break;
+ }
+
+ std::swap(data[i], data[pi]);
+ i = pi;
+ }
+ }
+
+ void siftDown(int i) {
+ while (i < count) {
+ int li = lhs(i);
+ int ri = rhs(i);
+
+ if (li < count) {
+ if (comparator(data[li], data[i])) {
+ if (ri < count && comparator(data[ri], data[li])) {
+ std::swap(data[i], data[ri]);
+ i = ri;
+ } else {
+ std::swap(data[i], data[li]);
+ i = li;
+ }
+ } else if (ri < count && comparator(data[ri], data[i])) {
+ std::swap(data[i], data[ri]);
+ i = ri;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+
+ public:
+
+ Heap() :
+ count(0)
+ {
+ // empty
+ }
+
+ Heap(const Heap<T,C>& other) {
+ data.resize(other.data.size());
+ for (int i = 0; i < other.count; ++i) {
+ data[i] = other.data[i];
+ }
+ count = other.count;
+ }
+
+ const Heap<T,C>& operator=(const Heap<T,C>& other) {
+ data.resize(other.data.size());
+ for (int i = 0; i < other.count; ++i) {
+ data[i] = other.data[i];
+ }
+ count = other.count;
+ return *this;
+ }
+
+ bool empty() const { return 0 == count; }
+
+ T& top() { return data[0]; }
+
+ void push(T item) {
+ int i = count++;
+ data.push_back(item);
+ siftUp(i);
+ }
+
+ void pop() {
+ data[0] = data[--count];
+ data.resize(count);
+ siftDown(0);
+ }
+
+ void updateTop() {
+ siftDown(0);
+ }
+
+ void clear() {
+ count = 0;
+ data.resize(0);
+ }
+
+ iterator begin() {
+ return iterator(*this, 0);
+ }
+
+ iterator end() {
+ return iterator(*this, count);
+ }
+
+ std::ostream& displaySorted(std::ostream& out,
+ std::function<bool(const T&)> filter,
+ bool insert_line_breaks = true) const {
+ Heap<T,C> temp = *this;
+
+ bool first = true;
+ out << "[ ";
+
+ while(!temp.empty()) {
+ const T& top = temp.top();
+ if (filter(top)) {
+ if (!first) {
+ out << ", ";
+ }
+ if (insert_line_breaks) {
+ out << std::endl << " ";
+ }
+ out << temp.top();
+ first = false;
+ }
+ temp.pop();
+ }
+
+ out << " ]";
+ if (insert_line_breaks) {
+ out << std::endl;
+ }
+ return out;
+ }
+
+ template<typename T1, typename T2>
+ friend std::ostream& operator<<(std::ostream&, const Heap<T1,T2>&);
+ }; // class Heap
+
+
+ template<typename T1, typename T2>
+ std::ostream& operator<<(std::ostream& out, const Heap<T1,T2>& h) {
+ out << "[ ";
+ if (h.count) {
+ out << h.data[0];
+ }
+ for (int i = 1; i < h.count; i++) {
+ out << ", " << h.data[i];
+ }
+ out << " ]";
+ return out;
+ }
+} // namespace