图算法-最小生成树之Bellman-ford

#include <iostream>
#include <map>
#include <functional>
#include <initializer_list>
enum:int{ MAXVALUE = 999 }; //匿名枚举类型.
template<typename T>
struct Edge{
 T startNode;
 T endNode;
 
 Edge()=default;
 
 template<typename Ty>
 Edge(const Ty& startNode_, const Ty& endNode_);
};
template<typename T>
template<typename Ty>
Edge<T>::Edge(const Ty& startNode_, const Ty& endNode_)
        :startNode(startNode_),
         endNode(endNode_)
{
 //
}
template<typename T>
class Graph{
 private:
  std::map<T, std::map<T, int>> edges; //存储边. 
  std::map<T, int> vertices; //存储顶点. 
  Edge<T>* edgeArray;
  bool flag;
  
  int nodeNumber;
  int edgeNumber;
  
  template<typename Ty>
  void initialize_single_source(const Ty& source_)noexcept;
   
  template<typename Ty>
  void relax(const Ty& source_)noexcept;
  
  public:
   template<typename Ty, unsigned int N>
   Graph(const std::initializer_list<Ty>& vertices_, const Ty (&edges_)[N][3]);
   
   ~Graph();
   
   template<typename Ty>
   void Bellman_ford(const Ty& source_);
   
   template<typename Ty>
   void printPath(const Ty& source_)const;
};
template<typename T>
template<typename Ty, unsigned int N>
Graph<T>::Graph(const std::initializer_list<Ty>& vertices_, const Ty (&edges_)[N][3])
         :flag(false)
{
 if(N == 0 || vertices_.size() == 0){
  throw std::runtime_error("it is empty in the graph");
 }
 
 this->nodeNumber = vertices_.size();
 this->edgeNumber = N;
 
 this->edgeArray = new Edge<Ty>[N]; //存储各个边的结点值. 
 
 typename std::initializer_list<Ty>::iterator it = vertices_.begin();
 
 for(; it != vertices_.end(); ++it){
  this->vertices[*it] = MAXVALUE;
 }
 
 for(int i=0; i<N; ++i){
  Edge<Ty> edge(edges_[i][0], edges_[i][1]);
  this->edges[edges_[i][0]][edges_[i][1]] = edges_[i][2];
  this->edgeArray[i]=edge;
 }
 
 std::cout<<"out of constructor"<<std::endl;
}
template<typename T>
template<typename Ty>
void Graph<T>::initialize_single_source(const Ty& source_)noexcept
{
 this->vertices[source_] = 0; //make the source node'degree of the graph 0; others is MAXVALUE.
}
template<typename T>
template<typename Ty>
void Graph<T>::relax(const Ty& source_)noexcept //noexcept show that the function can not throw exception;
{
 for(int i=1; i<this->nodeNumber; ++i){
  
  for(int j=0; j<this->edgeNumber; ++j){
   
   if(this->vertices[source_] != MAXVALUE){
    
    if(this->vertices[this->edgeArray[j].endNode] > this->vertices[this->edgeArray[j].startNode] + this->edges[this->edgeArray[j].startNode][this->edgeArray[j].endNode]){
     this->vertices[this->edgeArray[j].endNode] = this->vertices[this->edgeArray[j].startNode] + this->edges[this->edgeArray[j].startNode][this->edgeArray[j].endNode];
     //这两行写的比较长=.=
     //其中this->vertices[this->edgeArray[j].startNode]获得的是该边的顶结点的distance(注:distance是指的是从当前顶点到source_这个给定顶点的距离).
     //this->vertices[this->edgeArray[j].endNode]获得的是改变尾结点的distance. 
     
     
    }
   }
  }
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::Bellman_ford(const Ty& source_)
{
 this->initialize_single_source(source_);
 this->relax(source_);
 
 
 for(int i=0; i<this->edgeNumber; ++i){
  
  if(this->vertices[this->edgeArray[i].endNode] > this->vertices[this->edgeArray[i].startNode] + this->edges[this->edgeArray[i].startNode][this->edgeArray[i].endNode]){
   this->flag = false;
   break;
  }
 }
 
 this->flag = true;
 
 this->printPath(source_);
}
template<typename T>
Graph<T>::~Graph()
{
 if( !this->edges.empty() ){
  this->edges.clear();
 }
 
 if( !this->vertices.empty() ){
  this->vertices.clear();
 }
 
 if(this->edgeArray != nullptr){
  delete[] edgeArray;
  this->edgeArray = nullptr;
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::printPath(const Ty& source_)const
{
 if( this->flag == false ){
  std::cout<<"there is not the shortest way."<<std::endl;
  
 }else{
  
  typename std::map<Ty, int>::const_iterator it = this->vertices.cbegin();
  
  for(int i=0; i<this->nodeNumber; ++i){
   std::cout<<source_<<"  "<<it->first<<"   "<<it->second<<std::endl;
  }
 }
}
int main()
{
 int edges_[][3]={{0,1, 5}, {0,2, 8}, {0,3, -4}, {1,0, -2},  
                      {2,1, -3}, {2,3, 9}, {3,1, 7}, {3,4, 2},  
                      {4,0, 6}, {4,2, 7}};
                      
 Graph<int> myGraph({0, 1, 2, 3, 4}, edges_);
 myGraph.Bellman_ford(3);
 return 0;
 
}

你可能感兴趣的:(图算法-最小生成树之Bellman-ford)