#include <iostream> #include <map> #include <memory> #include <new> #include <stdexcept>
namespace{ enum : int{ MAXVALUE = 9999 }; }
template<typename T> class Graph{ private: std::map<T, std::map<T, int>> graph_; //存储有向图. std::map<T, std::map<T, T>> path_; //存储图中两个结点间的中间结点. std::map<T, std::map<T, int>> distance_; //存储两个结点间的距离. unsigned int node_number_; void floyd_warshall()noexcept; template<typename Ty> void print_path(const Ty& start_, const Ty& end_); public: using map_type = std::map<T, std::map<T, int>>; using map_iter = typename std::map<T, std::map<T, int>>::const_iterator; using iter = typename std::map<T, int>::const_iterator; template<typename Ty, unsigned int N> Graph(const Ty (&edges)[N][3]); ~Graph(); template<typename Ty> void print(const Ty& start, const Ty& end); };
template<typename T> template<typename Ty, unsigned int N> Graph<T>::Graph(const Ty (&edges)[N][3]) :node_number_(N) { if(N == 0){ throw std::runtime_error(std::string("there is nothing")); } /*for(int i=0; i<N; ++i){ for(int j=0; j<N; ++j){ (this->*graph_)[i][j] = (i == j) ? 0 : ::MAXVALUE; //如果该点的距离为从自身到自身那么距离为0. } }*/ for(int j =0; j<N; ++j){ (this->graph_)[edges[j][0]][edges[j][1]] = edges[j][2]; } map_iter first_ = (this->graph_).cbegin(); for(; first_ != (this->graph_).cend(); ++first_){ map_iter second_ = (this->graph_).cbegin(); for(; second_ != (this->graph_).cend(); ++second_){ if(first_->first == second_->first){ (this->graph_)[first_->first][second_->first] = 0; }else if((this->graph_)[first_->first][second_->first] > 0){ continue; }else{ (this->graph_)[first_->first][second_->first] = ::MAXVALUE; } } } std::cout<<"successful constructor\n"; /*map_iter iter_first = this->graph_.cbegin(); for(; iter_first != this->graph_.cend(); ++iter_first){ std::cout<<iter_first->first<<": "; iter iter_second = this->graph_[iter_first->first].cbegin(); for(; iter_second != this->graph_[iter_first->first].cend(); ++iter_second){ std::cout<<iter_second->first<<"--"<<iter_second->second<<" "; } std::cout<<std::endl; }*/ }
template<typename T> void Graph<T>::floyd_warshall()noexcept { if(this->node_number_ == 0){ throw std::runtime_error(std::string("there nothing in graph")); } //注意下面的双重循环: //first_, second_, 以first_为起点second_为终点不断的查找这两个结点间的距离. map_iter first_ = (this->graph_).cbegin(); for(; first_ != (this->graph_).cend(); ++first_){ map_iter second_ = (this->graph_).cbegin(); for(; second_ != (this->graph_).cend(); ++second_){ //std::cout<<"dis_: "<<(this->graph_)[first_->first][second_->first]<<std::endl; this->distance_[first_->first][second_->first] = (this->graph_)[first_->first][second_->first]; this->path_[first_->first][second_->first] = 0; } } /*std::cout<<'\n'<<"distance_"<<std::endl; map_iter x = this->distance_.cbegin(); for(; x != this->distance_.cend(); ++x){ std::cout<<x->first<<": "; iter y = (this->distance_)[x->first].cbegin(); for(; y != (this->distance_)[x->first].cend(); ++y){ std::cout<<y->first<<"--"<<y->second<<" "; } std::cout<<std::endl; }*/ //假设third_为从forth_到fifth_的中间结点. 来不断的寻找两个结点间的最短路径. map_iter third_ = (this->graph_).cbegin(); for(; third_ != (this->graph_).cend(); ++third_){ map_iter forth_ = (this->graph_).cbegin(); for(; forth_ != (this->graph_).cend(); ++forth_){ map_iter fifth_ = (this->graph_).cbegin(); for(; fifth_ != (this->graph_).cend(); ++fifth_){ /*std::cout<<"i-k:"<<(this->distance_)[forth_->first][third_->first]<<" "; std::cout<<"k-j:"<<(this->distance_)[third_->first][fifth_->first]<<" "; std::cout<<"i-j:"<<(this->distance_)[forth_->first][fifth_->first]<<" \n"; */ /*std::cout<<"i: "<<forth_->first<<" "; std::cout<<"j: "<<fifth_->first<<" "; std::cout<<"k: "<<third_->first<<" \n";*/ if((this->distance_)[forth_->first][third_->first]+(this->distance_)[third_->first][fifth_->first] < (this->distance_)[forth_->first][fifth_->first]){ std::cout<<"enter"<<std::endl; (this->distance_)[forth_->first][fifth_->first] = this->distance_[forth_->first][third_->first] + this->distance_[fifth_->first][third_->first]; (this->path_)[forth_->first][fifth_->first] = third_->first; //path存储从forth_到fifth_经过的结点. } } } } /*typename std::map<T, std::map<T, T>>::const_iterator begin_ = (this->path_).begin(); for(; begin_ != (this->path_).cend(); ++begin_){ std::cout<<begin_->first<<": "; typename std::map<T, T>::const_iterator end_ = (this->path_)[begin_->first].cbegin(); for(; end_ != (this->path_)[begin_->first].cend(); ++end_){ std::cout<<end_->first<<"--"<<end_->second<<" "; } std::cout<<std::endl; }*/ }
template<typename T> template<typename Ty> void Graph<T>::print(const Ty& start, const Ty& end) { this->floyd_warshall(); this->print_path(start, end); }
template<typename T> template<typename Ty> void Graph<T>::print_path(const Ty& start_, const Ty& end_) { if(start_ == end_){ throw std::runtime_error(std::string("there is no way")); } if(this->path_[start_][end_] == 0){ std::cout<<end_<<" "; }else{ this->print_path(start_, this->path_[start_][end_]); this->print_path(this->path_[start_][end_], end_); } }
template<typename T> Graph<T>::~Graph() { if(!this->graph_.empty()){ this->graph_.clear(); } if(!this->path_.empty()){ this->path_.clear(); } if(!this->distance_.empty()){ this->distance_.clear(); } }
int main() { int edges[15][3]={ {1, 2, 2}, {1, 4, 20}, {2, 5, 1}, {3, 1, 3}, {4, 3, 8}, {4, 6, 6}, {4, 7, 4}, {5, 3, 4}, {5, 8, 3}, {6, 3, 1}, {7, 8, 1}, {8, 6, 2}, {8, 10, 2}, {9, 7, 2}, {10, 9, 1} }; Graph<int> my_graph(edges); my_graph.print(1, 3); return 0; }