You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
5.3 KiB
143 lines
5.3 KiB
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <numeric>
|
|
|
|
#include "storm-config.h"
|
|
|
|
#include "storm/utility/macros.h"
|
|
|
|
namespace storm {
|
|
namespace storage {
|
|
|
|
template<typename Compare = std::less<uint64_t>>
|
|
class ConsecutiveUint64DynamicPriorityQueue {
|
|
public:
|
|
typedef uint64_t T;
|
|
typedef std::vector<T> Container;
|
|
|
|
private:
|
|
Container container;
|
|
Compare compare;
|
|
|
|
std::vector<uint64_t> positions;
|
|
|
|
public:
|
|
explicit ConsecutiveUint64DynamicPriorityQueue(uint64_t numberOfIntegers, Compare const& compare) : container(numberOfIntegers), compare(compare), positions(numberOfIntegers) {
|
|
std::iota(container.begin(), container.end(), 0);
|
|
std::make_heap(container.begin(), container.end(), compare);
|
|
updatePositions();
|
|
}
|
|
|
|
void increase(uint64_t element) {
|
|
uint64_t position = positions[element];
|
|
if (position >= container.size()) {
|
|
return;
|
|
}
|
|
|
|
uint64_t parentPosition = (position - 1) / 2;
|
|
while (position > 0 && compare(container[parentPosition], container[position])) {
|
|
std::swap(positions[container[parentPosition]], positions[container[position]]);
|
|
std::swap(container[parentPosition], container[position]);
|
|
|
|
position = parentPosition;
|
|
parentPosition = (position - 1) / 2;
|
|
}
|
|
|
|
STORM_LOG_ASSERT(std::is_heap(container.begin(), container.end(), compare), "Heap structure lost.");
|
|
}
|
|
|
|
bool contains(uint64_t element) const {
|
|
return positions[element] < container.size();
|
|
}
|
|
|
|
bool empty() const {
|
|
return container.empty();
|
|
}
|
|
|
|
std::size_t size() const {
|
|
return container.size();
|
|
}
|
|
|
|
const T& top() const {
|
|
return container.front();
|
|
}
|
|
|
|
void push(uint64_t const& item) {
|
|
container.emplace_back(item);
|
|
std::push_heap(container.begin(), container.end(), compare);
|
|
}
|
|
|
|
void pop() {
|
|
if (container.size() > 1) {
|
|
// Swap max element to back.
|
|
std::swap(positions[container.front()], positions[container.back()]);
|
|
std::swap(container.front(), container.back());
|
|
container.pop_back();
|
|
|
|
// Sift down the element from the top.
|
|
uint64_t positionToSift = 0;
|
|
uint64_t child = 2 * positionToSift + 1;
|
|
|
|
while (child < container.size()) {
|
|
if (child + 1 < container.size()) {
|
|
// Figure out larger child.
|
|
child = compare(container[child], container[child + 1]) ? child + 1 : child;
|
|
|
|
// Check if we need to sift down.
|
|
if (compare(container[positionToSift], container[child])) {
|
|
std::swap(positions[container[positionToSift]], positions[container[child]]);
|
|
std::swap(container[positionToSift], container[child]);
|
|
|
|
positionToSift = child;
|
|
child = 2 * positionToSift + 1;
|
|
} else {
|
|
break;
|
|
}
|
|
} else if (compare(container[positionToSift], container[child])) {
|
|
std::swap(positions[container[positionToSift]], positions[container[child]]);
|
|
std::swap(container[positionToSift], container[child]);
|
|
|
|
positionToSift = child;
|
|
child = 2 * positionToSift + 1;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
container.pop_back();
|
|
}
|
|
|
|
STORM_LOG_ASSERT(std::is_heap(container.begin(), container.end(), compare), "Heap structure lost.");
|
|
}
|
|
|
|
T popTop() {
|
|
T item = top();
|
|
pop();
|
|
return item;
|
|
}
|
|
|
|
private:
|
|
bool checkPositions() const {
|
|
uint64_t position = 0;
|
|
for (auto const& e : container) {
|
|
if (positions[e] != position) {
|
|
return false;
|
|
}
|
|
++position;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void updatePositions() {
|
|
uint64_t position = 0;
|
|
for (auto const& e : container) {
|
|
positions[e] = position;
|
|
++position;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|