266 lines
6.3 KiB
C++
266 lines
6.3 KiB
C++
#ifndef BINARY_HEAP_H
|
|
#define BINARY_HEAP_H
|
|
|
|
#include <boost/assert.hpp>
|
|
#include <boost/heap/d_ary_heap.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <limits>
|
|
#include <map>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace osrm
|
|
{
|
|
namespace util
|
|
{
|
|
|
|
template <typename NodeID, typename Key> class GenerationArrayStorage
|
|
{
|
|
using GenerationCounter = std::uint16_t;
|
|
|
|
public:
|
|
explicit GenerationArrayStorage(std::size_t size)
|
|
: positions(size, 0), generation(1), generations(size, 0)
|
|
{
|
|
}
|
|
|
|
Key &operator[](NodeID node)
|
|
{
|
|
generation[node] = generation;
|
|
return positions[node];
|
|
}
|
|
|
|
Key peek_index(const NodeID node) const
|
|
{
|
|
if (generations[node] < generation)
|
|
{
|
|
return std::numeric_limits<Key>::max();
|
|
}
|
|
return positions[node];
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
generation++;
|
|
// if generation overflows we end up at 0 again and need to clear the vector
|
|
if (generation == 0)
|
|
{
|
|
generation = 1;
|
|
std::fill(generations.begin(), generations.end(), 0);
|
|
}
|
|
}
|
|
|
|
private:
|
|
GenerationCounter generation;
|
|
std::vector<GenerationCounter> generations;
|
|
std::vector<Key> positions;
|
|
};
|
|
|
|
template <typename NodeID, typename Key> class ArrayStorage
|
|
{
|
|
public:
|
|
explicit ArrayStorage(std::size_t size) : positions(size, 0) {}
|
|
|
|
~ArrayStorage() {}
|
|
|
|
Key &operator[](NodeID node) { return positions[node]; }
|
|
|
|
Key peek_index(const NodeID node) const { return positions[node]; }
|
|
|
|
void Clear() {}
|
|
|
|
private:
|
|
std::vector<Key> positions;
|
|
};
|
|
|
|
template <typename NodeID, typename Key> class MapStorage
|
|
{
|
|
public:
|
|
explicit MapStorage(std::size_t) {}
|
|
|
|
Key &operator[](NodeID node) { return nodes[node]; }
|
|
|
|
void Clear() { nodes.clear(); }
|
|
|
|
Key peek_index(const NodeID node) const
|
|
{
|
|
const auto iter = nodes.find(node);
|
|
if (nodes.end() != iter)
|
|
{
|
|
return iter->second;
|
|
}
|
|
return std::numeric_limits<Key>::max();
|
|
}
|
|
|
|
private:
|
|
std::map<NodeID, Key> nodes;
|
|
};
|
|
|
|
template <typename NodeID, typename Key> class UnorderedMapStorage
|
|
{
|
|
public:
|
|
explicit UnorderedMapStorage(std::size_t) { nodes.rehash(1000); }
|
|
|
|
Key &operator[](const NodeID node) { return nodes[node]; }
|
|
|
|
Key peek_index(const NodeID node) const
|
|
{
|
|
const auto iter = nodes.find(node);
|
|
if (std::end(nodes) != iter)
|
|
{
|
|
return iter->second;
|
|
}
|
|
return std::numeric_limits<Key>::max();
|
|
}
|
|
|
|
Key const &operator[](const NodeID node) const
|
|
{
|
|
auto iter = nodes.find(node);
|
|
return iter->second;
|
|
}
|
|
|
|
void Clear() { nodes.clear(); }
|
|
|
|
private:
|
|
std::unordered_map<NodeID, Key> nodes;
|
|
};
|
|
|
|
template <typename NodeID,
|
|
typename Key,
|
|
typename Weight,
|
|
typename Data,
|
|
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
|
class BinaryHeap
|
|
{
|
|
public:
|
|
using WeightType = Weight;
|
|
using DataType = Data;
|
|
|
|
explicit BinaryHeap(std::size_t maxID) : node_index(maxID) { Clear(); }
|
|
|
|
void Clear()
|
|
{
|
|
heap.clear();
|
|
inserted_nodes.clear();
|
|
node_index.Clear();
|
|
}
|
|
|
|
std::size_t Size() const { return heap.size(); }
|
|
|
|
bool Empty() const { return 0 == Size(); }
|
|
|
|
void Insert(NodeID node, Weight weight, const Data &data)
|
|
{
|
|
const auto index = static_cast<Key>(inserted_nodes.size());
|
|
const auto handle = heap.push(std::make_pair(weight, index));
|
|
inserted_nodes.emplace_back(node, handle, weight, data);
|
|
node_index[node] = index;
|
|
}
|
|
|
|
Data &GetData(NodeID node)
|
|
{
|
|
const auto index = node_index.peek_index(node);
|
|
return inserted_nodes[index].data;
|
|
}
|
|
|
|
Data const &GetData(NodeID node) const
|
|
{
|
|
const auto index = node_index.peek_index(node);
|
|
return inserted_nodes[index].data;
|
|
}
|
|
|
|
const Weight &GetKey(NodeID node) const
|
|
{
|
|
const auto index = node_index.peek_index(node);
|
|
return inserted_nodes[index].weight;
|
|
}
|
|
|
|
bool WasRemoved(const NodeID node) const
|
|
{
|
|
BOOST_ASSERT(WasInserted(node));
|
|
const Key index = node_index.peek_index(node);
|
|
return inserted_nodes[index].handle == HeapHandle{};
|
|
}
|
|
|
|
bool WasInserted(const NodeID node) const
|
|
{
|
|
const auto index = node_index.peek_index(node);
|
|
if (index >= static_cast<decltype(index)>(inserted_nodes.size()))
|
|
{
|
|
return false;
|
|
}
|
|
return inserted_nodes[index].node == node;
|
|
}
|
|
|
|
NodeID Min() const
|
|
{
|
|
BOOST_ASSERT(!heap.empty());
|
|
return inserted_nodes[heap.top().second].node;
|
|
}
|
|
|
|
Weight MinKey() const
|
|
{
|
|
BOOST_ASSERT(!heap.empty());
|
|
return heap.top().first;
|
|
}
|
|
|
|
NodeID DeleteMin()
|
|
{
|
|
BOOST_ASSERT(!heap.empty());
|
|
const Key removedIndex = heap.top().second;
|
|
heap.pop();
|
|
inserted_nodes[removedIndex].handle = HeapHandle{};
|
|
return inserted_nodes[removedIndex].node;
|
|
}
|
|
|
|
void DeleteAll()
|
|
{
|
|
std::for_each(inserted_nodes.begin(), inserted_nodes.end(), [](auto &node) {
|
|
node.handle = HeapHandle();
|
|
});
|
|
heap.clear();
|
|
}
|
|
|
|
void DecreaseKey(NodeID node, Weight weight)
|
|
{
|
|
BOOST_ASSERT(!WasRemoved(node));
|
|
const auto index = node_index.peek_index(node);
|
|
auto &reference = inserted_nodes[index];
|
|
reference.weight = weight;
|
|
heap.increase(reference.handle, std::make_pair(weight, index));
|
|
}
|
|
|
|
private:
|
|
using HeapData = std::pair<Weight, Key>;
|
|
using HeapContainer = boost::heap::d_ary_heap<HeapData,
|
|
boost::heap::arity<4>,
|
|
boost::heap::mutable_<true>,
|
|
boost::heap::compare<std::greater<HeapData>>>;
|
|
using HeapHandle = typename HeapContainer::handle_type;
|
|
|
|
class HeapNode
|
|
{
|
|
public:
|
|
HeapNode(NodeID n, HeapHandle h, Weight w, Data d)
|
|
: node(n), handle(h), weight(w), data(std::move(d))
|
|
{
|
|
}
|
|
|
|
NodeID node;
|
|
HeapHandle handle;
|
|
Weight weight;
|
|
Data data;
|
|
};
|
|
|
|
std::vector<HeapNode> inserted_nodes;
|
|
HeapContainer heap;
|
|
IndexStorage node_index;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif // BINARY_HEAP_H
|