#include <iostream> #include <queue> #include <stdexcept> //throw std::runtime_error("xx"); #include <initializer_list> #include <map>
template<typename T> struct Edge{ T start_; T end_; int weighting_; Edge()=default; template<typename Ty> Edge(const Ty& start, const Ty& end, const int& wg); template<typename Ty> Edge(const Edge<Ty>& otherEdge); ~Edge()=default; };
template<typename T> template<typename Ty> Edge<T>::Edge(const Ty& start, const Ty& end, const int& wg) :start_(start), end_(end), weighting_(wg) { // }
template<typename T> template<typename Ty> Edge<T>::Edge(const Edge<Ty>& otherEdge) :start_(otherEdge.start_), end_(otherEdge.end_), weighting_(otherEdge.weighting_) { // }
class Compare{ //Compare用于prioprity_queue中的比较参数. public: template<typename Ty> bool operator()(const Ty& first_, const Ty& second_) { return first_ < second_ ? true : false; } };
template<typename T> class Graph{ private: Edge<T>* edgeArray; //store the start-node and end-node, the weighting between start-node and end-node; std::map<T, bool> visited_; //每个顶点都对应一个bool值, 访问过的话该bool值会被设置为true; std::map<T, std::vector<T>> edges_; //邻接链表.即,每一个顶点与其他顶点相接,其他顶点都被放在vector<T>中. std::priority_queue<T, std::vector<T>, Compare> cycle_; //如果该顶点有环路那么吧该顶点放入到cycle_; std::map<T, bool> haveCycle_; //判断该点时候存在环路. //std::multimap<T, T> edgeTo_; std::vector<T> result_; int edgeNumber_; bool flag_; //判断该有向加权图中是否存在回路.默认为true; public: template<typename Ty> using iter = typename std::map<Ty, bool>::iterator; template<typename Ty, unsigned int N> Graph(const Ty (&edges)[N][3]); template<typename Ty> void dfs(const Ty& node_); void helperFunction(); void print(); ~Graph(); };
template<typename T> template<typename Ty, unsigned int N> Graph<T>::Graph(const Ty (&edges)[N][3]) :edgeArray(nullptr), edgeNumber_(N), flag_(true) { if( N == 0 ){ std::runtime_error("The Graph has cycle.\n"); } this->edgeArray = new Edge<Ty>[N]; //存储有向图的各个条边以及该边的加权值. for(int i=0; i<N; ++i){ //存储有向加权图,且存储有向加权图的每一个结点.默认都是未被访问过的因此其对应的值为false. Edge<Ty> edge(edges[i][0], edges[i][1], edges[i][2]); this->edgeArray[i] = edge; this->visited_[edges[i][0]] = false; this->visited_[edges[i][1]] = false; //this->haveCycle_[edges[i][0]] = false; //this->haveCycle_[edges[i][1]] = false; this->edges_[edges[i][0]].push_back(edges[i][1]); //邻接链表.即每个结点与其他结点相接,其他结点都被放在与该结点对应的std::vector中. } std::cout<<"out of constructor fucntion"<<std::endl; /*iter<Ty> it = this->haveCycle_.begin(); for(; it!=this->haveCycle_.end(); ++it){ std::cout<<it->first<<std::endl; }*/ }
template<typename T> template<typename Ty> void Graph<T>::dfs(const Ty& node_) //该算法是基于深度优先遍历的. { std::cout<<"node: "<<node_<<std::endl; this->visited_[node_] = true; //当前结点已经被访问.把其对应的属性设置为true; this->haveCycle_[node_] = true; //haveCycle_是一个存放具有环路结点的容器. int temp = this->edges_[node_].size(); //获得与该结点相接的结点的个数. for(int i=0; i<temp; ++i){ if( !this->flag_ ){ return; } if( !this->visited_[this->edges_[node_][i]] ){ //this->edgeTo_[this->edges_[node_][i]] = node_; this->dfs(this->edges_[node_][i]); }else if(this->haveCycle_[this->edges_[node_][i]]){ this->flag_ = false; std::cout<<"have cycle"<<std::endl; this->cycle_.push(node_); this->cycle_.push(this->edges_[node_][i]); } } this->result_.push_back(node_); this->haveCycle_[node_] = false; }
template<typename T> void Graph<T>::helperFunction() { Graph<T>::iter<T> it = this->visited_.begin(); for(; it != this->visited_.end(); ++it){ if( !this->visited_[it->first] ){ this->dfs(it->first); } } }
template<typename T> void Graph<T>::print() { if( !this->flag_ ){ std::cout<<"failed"<<std::endl; }else{ std::cout<<"successful"<<std::endl; Graph<T>::iter<T> it = this->haveCycle_.begin(); for(; it!=haveCycle_.end(); ++it){ std::cout<<it->first<<std::endl; } } }
template<typename T> Graph<T>::~Graph() { if(this->edgeArray != nullptr ){ delete[] edgeArray; } if( !this->visited_.empty() ){ this->visited_.clear(); } if( !this->edges_.empty() ){ this->edges_.clear(); } if( !this->haveCycle_.empty() ){ this->haveCycle_.clear(); } }
int main() { int edge[][3]={ {0,2, 6}, {0,6, 6}, {2,6, 7}, {2,5, 4}, {2,4, 2}, {6,5 -1}, {6,4, 1}, {5,4, -2}}; Graph<int> myGraph(edge); myGraph.helperFunction(); myGraph.print(); return 0; }