#include <iostream> #include <map> #include <vector> #include <stdexcept> #include <memory>
namespace{ enum : int{ MAXVALUE = 9999; }; }
template<typename T> class Node{ public: T key_; template<typename Ty> Node(const T& key); Node()=default; Node(const Node<T>& otherNode_); template<typename Ty> Node(Node<Ty>&& otherNode_); const Node<T>& operator=(const Node<T>& otherNode_); template<typename Ty> const Node<Ty>& operator=(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; using node_type = T; };
template<typename T> template<typename Ty> Node<T>::Node(const Ty& key) :key_(key) { //default constructor. }
template<typename T> Node<T>::Node(const Node<T>& otherNode_) :key_(otherNode_.key_) { //copy-constructor. }
template<typename T> template<typename Ty> Node<T>::Node(Node<Ty>&& otherNode_) :key_(otherNode_.key_) { //move-constructor. }
template<typename T> const Node<T>& Node<T>::operator=(const Node<T>& otherNode_) { this->key_ = otherNode_.key_; return *this; }
template<typename T> template<typename Ty> const Node<Ty>& Node<T>::operator=(Node<Ty>&& otherNode_) { this->key_ = otherNode_.key_; return *this; }
template<typename Ty> bool operator<(const Node<Ty>& first_, const Node<Ty>& second_) { return (first_.key_ < second_.key_) ? true : false; }
template<typename Ty> bool operator==(const Node<Ty>& first_, const Node<Ty>& second_) { return (first_.key_ == second_.key_) ? true : false; }
template<typename T> class Graph{ private: std::map<Node<T>, std::map<Node<T>, int>> graph_; //存储有向图.在下面的构造函数中会把新结点(默认为0)加入进去。 std::vector<Edge<T>> edges_; std::map<Node<T>, int> distance_; //保存从给定顶点到各个顶点所经过的路程. std::map<Node<T>, std::vector<Node<T>>> adjList_; unsigned int node_number_; T source_key_; template<typename Ty> void bellman_ford(const Ty& source_data); void initialize_single_source()noexcept; template<typename Ty> void relax(const Node<Ty>& first_, const Node<Ty>& second_)noexcept; template<typename edge_type> class Edge{ public: std::shared_ptr<Node<edge_type>> start_; std::shared_ptr<Node<edge_type>> end_; int weighting_; //该边的加权值. Edge()=default; template<typename Ty> Edge(const Ty& start, const Ty& end_); template<typename Ty> Edge(const Ty& start); template<typename Ty> Edge(const Node<Ty>& start); Edge(cosnt Edge<T>& otherEdge_); template<typename Ty> Edge(Edge<Ty>&& otherEdge_); const Edge<edge_type>& operator=(const Edge<edge_type>& otherEdge_); template<typename Ty> const Edge<Ty>& operator=(Edge<Ty>&& otherEdge_); ~Edge()=default; }; public: using map_iter = typename std::map<Node<T>, int>::const_iterator; using map_in_map_iter = typename std::map<Node<T>, std::map<Node<T>, int>>::const_iterator; using vec_iter = typename std::vector<Node<T>>::const_iterator; using mapVec_iter = typename std::map<Node<T>, std::vector<Node<T>>>::const_iterator; template<typename Ty, unsigned int N> Graph(const Ty (&edges)[N][3]); Graph()=default; template<typename Ty> void johnson_algorithm(const Ty& source_); ~Graph(); };
template<typename T> template<typename edge_type> template<typename Ty> Graph<T>::Edge<edge_type>::Edge(const Ty& start, const Ty& end) :start_(std::make_shared<Node<Ty>> (new Node<Ty>(start))), end_(std::make_shared<Node<Ty>> (new Node<Ty>(end))) { //the constructor of edge; }
template<typename T> template<typename edge_type> template<typename Ty> Graph<T>::Edge<edge_type>::Edge(const Ty& start) :start(std::make_shared<Node<Ty>>(new Node<Ty>(start))), end(nullptr), weighting_(::MAXVALUE) { //constructor; }
template<typename T> template<typename edge_type> template<typename Ty> Graph<T>::Edge<edge_type>::Edge(const Node<Ty>& start) :start_(std::make_shared<Node<Ty>> (new Noed<Ty>(start))), end_(nullptr), weighting_(::MAXVALUE) { //constructor; }
template<typename T> template<typename edge_type> Graph<T>::Edge<edge_type>::Edge(const Edge<edge_type>& otherEdge_) :start_(otherEdge_.start_), end_(otherEdge_.end_), weighting_(0) { //copy-constructor for edge; }
template<typename T> template<typename edge_type> template<typename Ty> Graph<T>::Edge<edge_type>::Edge(Edge<Ty>&& otherEdge_) :start_(otherEdge_.start_), end_(otherEdge_.end_), weighting_(otherEdge_.weighting_) { otherEdge_.start_.reset(nullptr); otherEdge.end_.reset(nullptr); //move-constructor for edge; }
template<typename T> template<typename edge_type> const Edge<edge_type>& Graph<T>::Edge<edge_type>::operator=(const Edge<edge_type>& otherEdge_) { this->start_ = otherEdge_.start_; this->end_ = otherEdge_.end_; this->weighting_ = otherEdge_.weighting_; return *this; //operator=; }
template<typename T> template<typename edge_type> template<typename Ty> const Edge<Ty>& Graph<T>::Edge<edge_type>::operator=(Edge<Ty>&& otherEdge_) { this->start_ = otherEdge_.start_; this->end_ = otherEdge_.end_; this->weighting_ = otherEdge_.weighting_; otherEdge_.start_.reset(nullptr); otherEdge_.end_.reset(nullptr); return *this; }
template<typename T> template<typename Ty, unsigned int N> Graph<T>::Graph(const Ty (&edges)[N][3]) :node_number_(N) //注意这里的node_number_ = N; { if(N == 0){ throw std::runtime_error(std::string("there is nothing in graph")); } Node<Ty> temp_node(0); //存储有向图. //同时新建一个结点(temp_node)该结点与图中其他结点的之间的加权值为0. for(int i=0; i<N; ++i){ Node<Ty> first_(edges[i][0]); Node<Ty> second_(edges[i][1]); this->graph_[first_][second_] = edges[i][2]; this->graph_[temp_node][first_] = 0; this->graph_[temp_node][second_] = 0; //this->new_graph_[first_][second_] = edges[i][2]; this->distance_.insert(std::pair<Node<Ty>, int>(first_, ::MAXVALUE)); this->distance_.insert(std::pair<Node<Ty>, int>(second_, ::MAXVALUE)); this->adjList_[first_].push_back(second_); //每个结点的邻接链表. } this->distance_.insert(std::pair<Node<Ty>, int>(temp_node, 0)); std::cout<<"construct a graph successfully!"<<std::endl; }
template<typename Ty> void Graph<T>::initialize_single_source()noexcept { Node<T> source_node(this->source_key_); this->distance_[source_node] = 0; //把源结点距离自己的距离初始化为0. }
template<typename T> template<typename Ty> void Graph<T>::bellman_ford(const Ty& source_data) { this->source_key_ = source_data; this->initialize_single_source(); for(int i=0; i<this->node_number_; ++i){ //注意这里的node_number_是N(N代表原图中结点的个数我们新加入的那个结点的是没有被算进去的). mapVec_iter iter_first_ = this->adjList_.cbegin(); for(; iter_first_ != this->adjList_.cend(); ++iter_first_){ vec_iter iter_second_ = this->adjList_[iter_first_->first].cbegin(); for(; iter_second_ != this->adjList_[iter_first_->first].cend(); ++iter_second_){ this->relax(iter_first_->first, *iter_second); } } } }
template<typename T> template<typename Ty> void Graph<T>::relax(const Node<Ty>& first_, const Node<Ty>& second_) { if(this->distance_[second_] > this->distance_[first_] + this->graph_[first_][second_]){ this->distance_[second_] = this->distance_[first_] + this->graph_[first_][second_]; } }
template<typename T> template<typename Ty> void Graph<T>::johnson_algorithm(const Ty& souece_) { }