最短路径生成树(c++版 Dijkstra(即时和延时))
来源:互联网 发布:淘宝尺寸文字自定义 编辑:程序博客网 时间:2024/06/07 16:20
EdgeWeightedDigraph.h
#pragma once#include <memory>#include <fstream>#include <stdexcept>template <typename T>class Dijkstra;template <typename T>class LazyDijkstra;template<typename T>class EdgeWeightedDigraph{private: class AdjacentcyList { public: class DiEdge { public: std::shared_ptr<DiEdge> next; int v; int w; T weight; public: DiEdge(const int& s,const int& e,const T& t):v(s),w(e),weight(t),next(nullptr) { } DiEdge() = default; int from() { return v; } int to() { return w; } T Weight() { return weight; } }; std::shared_ptr<DiEdge> head; class Iterator { private: std::shared_ptr<DiEdge> it; public: Iterator(std::shared_ptr<DiEdge> i) :it(i) { } bool operator == (const Iterator& rhs)const { return it == rhs.it; } bool operator != (const Iterator& rhs)const { return it != rhs.it; } Iterator operator ++() { it = it->next; return *this; } DiEdge operator *()const { if (it == nullptr) throw std::out_of_range("* nullptr error"); return *it; } }; Iterator begin()const { return Iterator(head); } Iterator end()const { return Iterator(nullptr); } AdjacentcyList():head(nullptr) { }/*****************************************函数名称: addDiEdge******************************************/ void addDiEdge(const int& s,const int& e,const T& t) { if (head == nullptr) { head = std::make_shared<DiEdge>(DiEdge(s, e, t)); return; } std::shared_ptr<DiEdge> curr = head; while (curr->next != nullptr) curr = curr->next; curr->next = std::make_shared<DiEdge>(DiEdge(s, e, t)); return; } };private: std::unique_ptr<AdjacentcyList[]> adj; int nV; int nE;public: EdgeWeightedDigraph(const std::string& file):nE(0) { std::ifstream in(file); in >> nV; adj = std::move(std::unique_ptr<AdjacentcyList[]>(new AdjacentcyList[nV])); while (!in.eof()) { int pre, curr; T weight; in >> pre >> curr >> weight; adj[pre].addDiEdge(pre, curr, weight); ++nE; } } friend class Dijkstra<T>; friend class LazyDijkstra<T>;};
辅助数据结构类优先队列: priority_queue.h
#pragma once#include <functional>#include <memory>template <typename T, typename Cmp = std::less<T>>class priority_queue{private: int SIZE = 100; std::unique_ptr<T[]> heap; int count;public: priority_queue():heap(new T[SIZE + 1]), count(0) { }private: void swim(int k) { while (k > 1 && Cmp()(heap[k], heap[k / 2])) { std::swap(heap[k], heap[k / 2]); k = k / 2; } } void sink(int k, const int& N) { while (2 * k <= N) { int j = 2 * k; if (j < N && Cmp()(heap[j + 1], heap[j])) ++j; if (Cmp()(heap[k], heap[j])) break; std::swap(heap[k], heap[j]); k = j; } } void resize(const int& n) { std::unique_ptr<T[]> tmp(new T[n + 1]); for (int i = 1; i <= count; ++i) tmp[i] = heap[i]; heap = std::move(tmp); SIZE = n; }public: void push(const T& t) { if (count == SIZE) resize(SIZE * 2); heap[++count] = t; swim(count); } T top() { if (count == 0) throw std::out_of_range("error of top"); return heap[1]; } void pop() { if (count == 0) return; if (count == 1) { --count; return; } std::swap(heap[1], heap[count]); --count; sink(1, count); if (count <= SIZE / 4) resize(SIZE / 2); } bool empty()const { return count == 0; }/****************for pair*****************/ void push(const int& i, const T& t) { if (count == 0) { push(t); return; } int pos = 1; for (pos = 1; pos <= count; ++pos) if (heap[pos].first == i) break; if (heap[pos].first == i) { if (count == 1) { heap[1] = t; return; } heap[pos] = heap[count]; --count; sink(pos, count); push(t); return; } else push(t); }/*---------------------------------------*/};
即时版 Dijkstra算法 Dijkstra.h
#pragma once#include "priority_queue.h"#include "EdgeWeightedDigraph.h"template <typename T>class Dijkstra{ using Ed = typename EdgeWeightedDigraph<T>::AdjacentcyList::DiEdge;private: class Less { public: Less() {} bool operator ()(const std::pair<int, T>& lhs, const std::pair<int, T>& rhs) { return lhs.second < rhs.second; } };private: std::unique_ptr<T[]> disTo; std::unique_ptr<Ed*[]> edge; priority_queue<std::pair<int, T>,Less> pq; int nv; int s;private: void relax(EdgeWeightedDigraph<T> *ewg,const int& i) { for (auto &e : ewg->adj[i]) { int w = e.to(); if (disTo[w] > disTo[i] + e.weight) { disTo[w] = disTo[i] + e.weight; edge[w] = new Ed(i, w, e.weight); pq.push(w, pair<int,T>(w,disTo[w])); } } }public: Dijkstra(EdgeWeightedDigraph<T>* ewd,const int& s = 0):disTo(new T[ewd->nV]),edge(new Ed*[ewd->nV]),nv(ewd->nV),s(s) { for (int i = 0; i < ewd->nV; ++i) { disTo[i] = std::numeric_limits<T>::max(); edge[i] = nullptr; } disTo[s] = T{}; pq.push(s, pair<int, T>(s, 0.0)); while (!pq.empty()) { relax(ewd, pq.top().first); pq.pop(); } } T min_weight() { T ret{}; for (int i = 0; i < nv; ++i) { if (edge[i] == nullptr) continue; cout << edge[i]->from() << ends << edge[i]->to() << ends << edge[i]->weight << endl; ret += edge[i]->weight; } return ret; }};
延时版Dijkstra算法 LazyDijkstra.h
#pragma once#include "EdgeWeightedDigraph.h"#include "priority_queue.h"template <typename T>class LazyDijkstra{ using Ed = typename EdgeWeightedDigraph<T>::AdjacentcyList::DiEdge;private: class Less { public: Less(){} bool operator()(const std::pair<Ed,T>& lhs, const std::pair<Ed,T>& rhs)const { return lhs.second < rhs.second; } };private: std::unique_ptr<bool[]> marked; std::unique_ptr<Ed*[]> edge; std::unique_ptr<T[]> disTo; priority_queue<std::pair<Ed,T>,Less> pq; int nv; int s; // 起点private: void relax(EdgeWeightedDigraph<T>* ewd,const int& i) { marked[i] = true; for (auto &e : ewd->adj[i]) { int w = e.to(); pq.push(std::pair<Ed,T>(e,disTo[w])); } }public: LazyDijkstra(EdgeWeightedDigraph<T> *ewd,const int& s = 0):marked(new bool[ewd->nV]),edge(new Ed*[ewd->nV]),disTo(new T[ewd->nV]),nv(ewd->nV),s(s) { for (int i = 0; i < ewd->nV; ++i) { edge[i] = nullptr; disTo[i] = std::numeric_limits<T>::max(); } disTo[s] = T{}; relax(ewd, s); while (!pq.empty()) { Ed e = pq.top().first; int v = e.from(); int w = e.to(); pq.pop(); if (disTo[w] > disTo[v] + e.weight) { disTo[w] = disTo[v] + e.weight; edge[w] = new Ed(v, w, e.weight); relax(ewd, w); } } } T min_weight() { T ret{}; for (int i = 0; i < nv; ++i) { if (edge[i] == nullptr) continue; cout << edge[i]->from() << ends << edge[i]->to() << ends << edge[i]->weight << endl; ret += edge[i]->weight; } return ret; }};
测试文件: test.txt
84 5 0.355 4 0.354 7 0.375 7 0.287 5 0.285 1 0.320 4 0.380 2 0.267 3 0.391 3 0.292 7 0.346 2 0.403 6 0.526 0 0.586 4 0.93
main.cpp
#include <iostream>#include "EdgeWeightedDigraph.h"#include "Dijkstra.h"#include "LazyDijkstra.h"using namespace std;int main(){ EdgeWeightedDigraph<double> ewd("test.txt"); Dijkstra<double> dj(&ewd,5); cout << "即时版Dijkstra: " << dj.min_weight() << endl; LazyDijkstra<double> ldj(&ewd,5); cout << "延时版Dijkstra: " << ldj.min_weight(); system("pause"); return 0;}
运行:
阅读全文
1 0
- 最短路径生成树(c++版 Dijkstra(即时和延时))
- 最短路径(C++版 Dijkstra即时版与延时版)
- Kruskal 最小生成树 & Dijkstra 最短路径
- dijkstra最短路径算法和普里姆最小生成树算法优化的关键
- 最小生成树算法(Prime、Kruskal)和最短路径算法(Dijkstra、Floyd)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 用PIL(Python-Imaging)反转图像的颜色
- UVA
- UISearchBar
- SVN使用方法
- Android中Activity四种启动模式和taskAffinity属性详解
- 最短路径生成树(c++版 Dijkstra(即时和延时))
- spring学习笔记 -- day13 基于XML的引入式整合
- 最大比合并(MRC)
- Web Server Gateway Interface (WSGI)
- 慕课笔记--[课程]React入门
- B
- iostat磁盘IO命令详解
- Lintcode 用栈实现队列
- 编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。