Dijikstra算法.
MilMcGrowdi
9年前
来自: http://my.oschina.net/u/2516597/blog/607688
#include <iostream> #include <priority_queue> #include <map> #include <stdexcept>
namespace{ static int MAXVALUE = 999; }
template<typename T> struct Node{ T node_; int weighting_; using node_type = T; template<typename Ty> Node(const Ty& node, const int& weighting); //构造函数. template<typename Ty> Node(Node<Ty>&& otherNode); //移动构造函数. template<typename Ty> Node(const Node<Ty>& otherNode); //拷贝构造函数. template<typename Ty> friend bool operator<(const Node<Ty>& first_, const Node<Ty>& second); template<typename Ty> friend bool operator==(const Node<Ty>& first_, const Node<Ty>& second_); ~Node()=default; };
template<typename T> template<typename Ty> Node<T>::Node(const Ty& node, const int& weighting) :node_(node), weighting_(weighting) { // }
template<typename T> template<typename Ty> Node<T>::Node(Node<Ty>&& otherNode) :node_(otherNode.node_), weighting_(otherNode.weighting_) { // std::cout<<"move-constructor"<<std::endl; }
template<typename T> template<typename Ty> Node<T>::Node(const Node<Ty>& otherNode) :node_(otherNode.onde_), weighting_(otherNode.weighting_) { // std::cout<<"copy for constructing"<<std::endl; }
template<typename Ty> bool operator<(const Node<Ty>& first_, const Node<Ty>& second_) { return (first_.weighting_ < second_.weighting_) ? true : false; }
template<typename Ty> bool operator==(const Node<Ty>& first_, const Node<Ty>& second_) { return (first_.node_ == second_.node_) ? true : false; }
class Compare{ public: template<typename Ty> bool operator<(const Node<Ty>& first_, const Node<Ty>& second_); };
template<typename Ty> bool Compare::operator<(const Node<Ty>& first_, const Node<Ty>& second_) { return first_ < second_; }
template<typename T> class Graph{ //所有边的加权值必须为正. private: std::map<Node<T>, std::map<Node<T>, int> edges_; //存储无向图的各个边的加权值. std::map<Node<T>, std::vector<Node>> adjList_; //每个结点所相接的结点的邻接链表. std::priority<Node<T>, std::vector<T>, Compare> vertices_; //按照各个结点weighting_的大小来进行比较,作为除了给定源点外其他结点的集合. std::vector<Node<T>> verticeArray_; //存储从vertices_中找到最短路径的集合. template<typename Ty> void relax(const Node<Ty>& first_, const Node<Ty>& second_); //松弛操作. public: template<typename Ty, unsigned int N> Graph( const Ty (&edges)[N][3] ); //构造函数. template<typename Ty> void Dijstra(const Ty& node_data); //Dijstra算法. ~Graph(); };
template<typename T> template<typename Ty, unsigned int N> Graph<T>::Graph( const Ty (&edges)[N][3] ) { if( N==0 ){ std::runtime_error("there is nothing in Graph.\n"); } for(int i=0; i<N; ++i){ Node<Ty> first_(edges[i][0], ::MAXVALUE); //这里之所以用::因为MAXVALUE位于匿名的namespace中. Node<Ty> second_(edges[i][1], ::MAXVALUE); //每个结点当前的加权值被设置为MAXVALUE. this->edges_[first_][second_] = edges[i][2]; //设置每条边相对应的加权值. this->adjList[first_].push_back(second_); //与first_相连的顶点被放在与其对应的std::vector中了. } std::cout<<"out of constructor."<<std::endl; }
template<typename T> void Graph<T>::relax(const Node<Ty>& first_, const Node<Ty>& second_) { if(second_.weighting_ > first_.weighting_ + this->edges_[first_][second_]){ //second_为first_的前驱结点. second_.weighting = first_.weighting_ + this->edges_[first_][second_]; //如果前驱结点的weighting_大于当前结点(first_)的weighting_. //那么把前驱结点的weighting_设置为当前结点的weighting_和first_跟second_之间加权值的和. } }
template<typename T> template<typename Ty> void Graph<T>::Dijstra(const Ty& node_data) { Node<Ty> source(node_data, 0); //设置源结点. 源结点的weighting_被设置为0. typename std::map<Node<Ty>, std::map<Node<T>, int>::const_iterator iter = this->edges_.begin(); //把所有的顶点存储到一个栈. this->verticeArray_.push_back(source); //把原点以及相距原点最短的结点都放入到verticeArray_中. for(; iter != this->edges_.end(); ++iter){ //把除了原点外的所有结点都放到vertices_中. if(source == iter->first){ continue; } this->vertices_.push(iter->first); } if( !this->vertices_.empty() ){ for(int i=0; i<this->vertices_.size(); ++i){ //逐个访问vertices_中的结点. Node<Ty> node = this->vertices_.top(); this->vertices_.pop(); this->verticeArray_.push_back(node); //把当前结点放到verticeArray_中. for(int j=0; j<this->adjList[node].size(); ++j){ //对于vertices_中各个结点相接的结点进行松弛操作. this->relax(node, adjList[node][j]); } } } }