Dijkstra uses priority queue

master
dmatetelki 10 years ago
parent 1a64773a66
commit 79b6b1b24d

@ -2,10 +2,11 @@
#define GRAPH_ALGORITHMS_HPP #define GRAPH_ALGORITHMS_HPP
#include "graph.hpp" #include "graph.hpp"
#include "priority_queue.hpp"
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <queue> #include <queue>
#include <set> #include <set>
@ -17,19 +18,6 @@
namespace { namespace {
template <typename V, typename W>
inline V closestNode(const std::unordered_set<V>& q, const std::unordered_map<V, std::pair<W, V> >& dist_prev)
{
const typename std::unordered_set<V>::const_iterator smallest_it =
std::min_element(q.begin(), q.end(),
[&dist_prev](const V& v1, const V& v2)
{ const auto v1_it = dist_prev.find(v1);
const auto v2_it = dist_prev.find(v2);
return !( v2_it != dist_prev.end() && ((v1_it == dist_prev.end()) || (v1_it->second.first > v2_it->second.first)) ); } );
return *smallest_it;
}
template <typename V, typename W> template <typename V, typename W>
std::vector<V> pathFromPrevList(const V& dest, const std::unordered_map<V, std::pair<W, V> >& dist_prev) std::vector<V> pathFromPrevList(const V& dest, const std::unordered_map<V, std::pair<W, V> >& dist_prev)
{ {
@ -60,15 +48,18 @@ dijkstra_shortest_path_to(const Graph<V>& graph,
std::unordered_map<V, std::pair<W, V> > dist_prev; std::unordered_map<V, std::pair<W, V> > dist_prev;
dist_prev.emplace(source, std::pair<W, V>(W(), V())); dist_prev.emplace(source, std::pair<W, V>(W(), V()));
std::unordered_set<V> q; // std::unordered_set<V> q;
PriorityQueue<W, V> q;
for (const auto& v : graph.neighboursOf(source)) { for (const auto& v : graph.neighboursOf(source)) {
q.insert(v); const W d = distanceCompute(source, v);
dist_prev.emplace(v, std::pair<W, V>(distanceCompute(source, v), source)); q.push(d, v);
dist_prev.emplace(v, std::pair<W, V>(d, source));
} }
while (!q.empty()) { while (!q.empty()) {
const V& u = closestNode<V, W>(q, dist_prev); const V u = q.top().second;
q.erase(u); q.pop();
if (u == dest) if (u == dest)
break; break;
@ -78,9 +69,14 @@ dijkstra_shortest_path_to(const Graph<V>& graph,
if (dist_prev.find(v) == dist_prev.end()) { // new node if (dist_prev.find(v) == dist_prev.end()) { // new node
dist_prev.emplace(v, std::pair<W, V>(alt, u)); dist_prev.emplace(v, std::pair<W, V>(alt, u));
q.insert(v); // q.insert(v);
} else if (alt < dist_prev.at(v).first) { // better route q.push(alt, v);
} else {
const W prev_d = dist_prev.at(v).first;
if (alt < prev_d) { // better route
dist_prev[v] = std::pair<W, V>(alt, u); dist_prev[v] = std::pair<W, V>(alt, u);
q.modifyKey(prev_d, v, alt);
}
} }
} }
} }

@ -37,11 +37,11 @@ public:
// modifiers // modifiers
void pop() { m_map.erase(m_map.begin()); } void pop() { m_map.erase(m_map.begin()); }
void push(const Key& key, const T& value) { m_map.emplace(key, value); } void push(const Key& key, const T& value) { m_map.emplace(key, value); }
void modifyKey(const T& value, const Key& diff) { void modifyKey(const Key& key, const T& value, const Key& new_key) {
auto it = std::find_if(m_map.begin(), m_map.end(), [&value](const std::pair<const Key, T> & p) { return p.second == value; } ); auto it = std::find_if(m_map.begin(), m_map.end(), [&key, &value](const std::pair<const Key, T> & p) { return p.first == key && p.second == value; } );
Key key = it->first; // take a copy T v = it->second; // take a copy
m_map.erase(it); m_map.erase(it);
m_map.emplace(key + diff, value); m_map.emplace(new_key, v);
} }
bool contains(const T& value) const { bool contains(const T& value) const {
@ -50,7 +50,7 @@ public:
} }
private: private:
std::map<Key, T, Compare, Allocator> m_map; std::multimap<Key, T, Compare, Allocator> m_map;
}; };
#endif // PRIORITY_QUEUE_HPP #endif // PRIORITY_QUEUE_HPP

Loading…
Cancel
Save