osrm-backend/include/util/binary_heap.hpp

266 lines
6.3 KiB
C++
Raw Normal View History

#ifndef BINARY_HEAP_H
#define BINARY_HEAP_H
2013-10-30 13:52:23 -04:00
#include <boost/assert.hpp>
2017-05-02 03:10:05 -04:00
#include <boost/heap/d_ary_heap.hpp>
#include <algorithm>
#include <cstddef>
#include <limits>
#include <map>
2014-05-05 10:21:41 -04:00
#include <type_traits>
#include <unordered_map>
#include <vector>
2016-01-05 10:51:13 -05:00
namespace osrm
{
namespace util
{
2017-04-04 07:33:34 -04:00
template <typename NodeID, typename Key> class GenerationArrayStorage
{
using GenerationCounter = std::uint16_t;
2017-04-05 06:23:53 -04:00
2017-04-04 07:33:34 -04:00
public:
2017-04-05 06:23:53 -04:00
explicit GenerationArrayStorage(std::size_t size)
: positions(size, 0), generation(1), generations(size, 0)
{
}
2017-04-04 07:33:34 -04:00
2017-04-05 06:23:53 -04:00
Key &operator[](NodeID node)
{
2017-04-04 07:33:34 -04:00
generation[node] = generation;
return positions[node];
}
2017-04-05 06:23:53 -04:00
Key peek_index(const NodeID node) const
{
2017-04-04 07:33:34 -04:00
if (generations[node] < generation)
{
return std::numeric_limits<Key>::max();
}
return positions[node];
}
2017-04-05 06:23:53 -04:00
void Clear()
{
2017-04-04 07:33:34 -04:00
generation++;
// if generation overflows we end up at 0 again and need to clear the vector
if (generation == 0)
2017-04-04 07:33:34 -04:00
{
generation = 1;
2017-04-04 07:33:34 -04:00
std::fill(generations.begin(), generations.end(), 0);
}
}
private:
GenerationCounter generation;
std::vector<GenerationCounter> generations;
std::vector<Key> positions;
};
2014-05-05 10:21:41 -04:00
template <typename NodeID, typename Key> class ArrayStorage
{
public:
explicit ArrayStorage(std::size_t size) : positions(size, 0) {}
~ArrayStorage() {}
2014-05-05 10:21:41 -04:00
Key &operator[](NodeID node) { return positions[node]; }
Key peek_index(const NodeID node) const { return positions[node]; }
void Clear() {}
2014-05-05 10:21:41 -04:00
private:
std::vector<Key> positions;
};
2014-05-05 10:21:41 -04:00
template <typename NodeID, typename Key> class MapStorage
{
public:
explicit MapStorage(std::size_t) {}
2014-05-05 10:21:41 -04:00
Key &operator[](NodeID node) { return nodes[node]; }
2014-05-05 10:21:41 -04:00
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();
}
2014-05-05 10:21:41 -04:00
private:
std::map<NodeID, Key> nodes;
};
2014-05-05 10:21:41 -04:00
template <typename NodeID, typename Key> class UnorderedMapStorage
{
public:
explicit UnorderedMapStorage(std::size_t) { nodes.rehash(1000); }
2014-05-05 10:21:41 -04:00
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();
}
2014-05-05 10:21:41 -04:00
Key const &operator[](const NodeID node) const
{
auto iter = nodes.find(node);
2014-02-26 09:55:04 -05:00
return iter->second;
}
2014-05-05 10:21:41 -04:00
void Clear() { nodes.clear(); }
2014-05-05 10:21:41 -04:00
private:
std::unordered_map<NodeID, Key> nodes;
};
2014-05-05 10:21:41 -04:00
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(); }
2014-05-05 10:21:41 -04:00
void Clear()
{
2017-05-02 03:10:05 -04:00
heap.clear();
2014-05-05 10:21:41 -04:00
inserted_nodes.clear();
node_index.Clear();
}
2017-05-02 03:10:05 -04:00
std::size_t Size() const { return heap.size(); }
2014-05-05 10:21:41 -04:00
bool Empty() const { return 0 == Size(); }
2013-09-21 15:51:07 -04:00
2014-05-05 10:21:41 -04:00
void Insert(NodeID node, Weight weight, const Data &data)
{
2017-05-02 03:10:05 -04:00
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;
}
2014-05-05 10:21:41 -04:00
Data &GetData(NodeID node)
{
2017-05-02 03:10:05 -04:00
const auto index = node_index.peek_index(node);
2014-05-05 10:21:41 -04:00
return inserted_nodes[index].data;
}
2014-05-05 10:21:41 -04:00
Data const &GetData(NodeID node) const
{
2017-05-02 03:10:05 -04:00
const auto index = node_index.peek_index(node);
2014-05-05 10:21:41 -04:00
return inserted_nodes[index].data;
2014-02-26 09:55:04 -05:00
}
const Weight &GetKey(NodeID node) const
{
2017-05-02 03:10:05 -04:00
const auto index = node_index.peek_index(node);
return inserted_nodes[index].weight;
}
bool WasRemoved(const NodeID node) const
2014-05-05 10:21:41 -04:00
{
BOOST_ASSERT(WasInserted(node));
const Key index = node_index.peek_index(node);
2017-05-02 03:10:05 -04:00
return inserted_nodes[index].handle == HeapHandle{};
}
bool WasInserted(const NodeID node) const
2014-05-05 10:21:41 -04:00
{
const auto index = node_index.peek_index(node);
2015-01-15 07:11:25 -05:00
if (index >= static_cast<decltype(index)>(inserted_nodes.size()))
2014-05-05 10:21:41 -04:00
{
return false;
2014-05-05 10:21:41 -04:00
}
return inserted_nodes[index].node == node;
}
2014-05-05 10:21:41 -04:00
NodeID Min() const
{
2017-05-02 03:10:05 -04:00
BOOST_ASSERT(!heap.empty());
return inserted_nodes[heap.top().second].node;
}
2016-01-05 06:04:04 -05:00
Weight MinKey() const
{
2017-05-02 03:10:05 -04:00
BOOST_ASSERT(!heap.empty());
return heap.top().first;
}
2014-05-05 10:21:41 -04:00
NodeID DeleteMin()
{
2017-05-02 03:10:05 -04:00
BOOST_ASSERT(!heap.empty());
const Key removedIndex = heap.top().second;
heap.pop();
inserted_nodes[removedIndex].handle = HeapHandle{};
2014-05-05 10:21:41 -04:00
return inserted_nodes[removedIndex].node;
}
2014-05-05 10:21:41 -04:00
void DeleteAll()
{
2017-05-02 03:10:05 -04:00
std::for_each(inserted_nodes.begin(), inserted_nodes.end(), [](auto &node) {
node.handle = HeapHandle();
});
heap.clear();
}
2014-05-05 10:21:41 -04:00
void DecreaseKey(NodeID node, Weight weight)
{
2017-05-02 03:10:05 -04:00
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));
}
2014-05-05 10:21:41 -04:00
private:
2017-05-02 03:10:05 -04:00
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;
2014-05-05 10:21:41 -04:00
class HeapNode
{
public:
2017-05-02 03:10:05 -04:00
HeapNode(NodeID n, HeapHandle h, Weight w, Data d)
: node(n), handle(h), weight(w), data(std::move(d))
{
}
NodeID node;
2017-05-02 03:10:05 -04:00
HeapHandle handle;
Weight weight;
Data data;
};
2014-05-05 10:21:41 -04:00
std::vector<HeapNode> inserted_nodes;
2017-05-02 03:10:05 -04:00
HeapContainer heap;
2014-05-05 10:21:41 -04:00
IndexStorage node_index;
};
2016-01-05 10:51:13 -05:00
}
}
2014-05-05 10:21:41 -04:00
#endif // BINARY_HEAP_H