Johnson算法

#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_);
  
  template<typename Ty>
  Node(Node<Ty>* node_ptr_);
  
  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>
template<typename Ty>
Node<T>::Node(const Node<Ty>* node_ptr_)
        :key_(node_ptr_.key_)
{
 //
}
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::map<Node<T>, int> distance_; //保存从给定顶点到各个顶点所经过的路程. 
  std::map<Node<T>, std::vector<Node<T>>> adjList_;
  
  std::map<Node<T>, bool> whether_visited_;  //用于dijstra算法. 判断当前结点是否被访问过,默认都为false. 
  std::vector<Node<T>> have_find_; //用于dijstra算法. 存放已经找到最短路径的结点. 
  std::map<Node<T>, Node<T>> node_to_node_;
  
  std::map<Node<T>, std::vector<Edge<T>>> one_for_all_; //当Node<T>作为源结点的时候,对应的有向图中源结点到各个结点的距离. 
  
  unsigned int node_number_;
  T source_key_;
  bool flag_;  //如果给定的有向图中存在负环路,那么flag_为true,否则为false.(默认为false). 
  
  template<typename Ty>
  void bellman_ford(const Ty& source_data); //之所以使用Bellman-ford算法是因为该算法允许存在权重为负数的边. 
  
  void initialize_single_source()noexcept;
  
  template<typename Ty>
  void relax(const Node<Ty>& first_, const Node<Ty>& second_)noexcept;
  
  template<typename Ty>
  void dijstra_algorithm(const Node<Ty>& node_)noexcept;
  
  template<typename Ty>
  void initialized_distance(const Node<Ty>& source_)noexcept;
  
  template<typename Ty>
  void relax_dijstra(const Node<Ty>& first_, const Node<Ty>& second_)noexcept;
  
  void transition()noexcept; //这是一个过渡函数用于bellman-ford算法结束后和Dijstra算法开始前.
  //其主要用于在bellman-ford算法执行结束后求得给定的源节点(source)到图中各个结点间的最短路径后把这些路径更新到graph_中. 
  
  template<typename Ty>
  void helper_function(const Node<Ty>& node_)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 Node<Ty>& first_, const Node<Ty>& second_);
   
   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)
                          :Edge(Node<Ty>(start), Node<Ty>(end))
{
 //the constructor of edge;
}
template<typename T>
template<typename edge_type>
template<typename Ty>
Graph<T>::Edge<edge_type>::Edge(const Node<Ty>& first_, const Node<Ty>& second_)
                          :start_(std::make_shared<Node<Ty>>(Node<Ty>(first_))),
                           end_(std::make_shared<Node<Ty>>(Node<Ty>(second_)))
{
 //
}
 
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();
 otherEdge.end_.reset();
 
 //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();
 otherEdge_.end_.reset();
 
 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;
          flag_(false)
{
 if(N == 0){
  throw std::runtime_error(std::string("there is nothing in graph"));
 }
 
 Node<Ty> temp_node(0); //temp_node作为我们新加入的结点. 
 
 //存储有向图. 
 //同时新建一个结点(temp_node)该结点与图中其他结点的之间的加权值为0. 
 for(int i=0; i<N; ++i){
  Node<Ty> first_(edges[i][0]);
  Node<Ty> second_(edges[i][1]);
  
  for(int j=0; j<N; ++j){
   Node<Ty> third_(edges[i][0]);
   
   if(first_ == third_){
    this->graph_[first_][third_] = 0;
    continue;
   }
   
   this->graph_[first_][third_] = ::MAXVALUE;
  } 
  
  this->graph_[first_][second_] = edges[i][2];
  this->graph_[temp_node][first_] = 0;
  this->graph_[temp_node][second_] = 0;
  
  
  
  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->whether_visited_[first_] = false;
  this->whether_visited_[second_] = false;
 }
 
 this->whether_visited_[temp_node] = false;
 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) //通过Bellman-ford算法求出 新加入的结点到各个结点的最短距离. 
{
 this->source_key_ = source_data;
 this->initialize_single_source();
 
 for(int 1=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);
   }
  }
 }
 
 mapVec_iter iter_third_ = this->adjList_.cbegin();
 for(; iter_third_ != this->adjList_.cend(); ++iter_third_){ //判断是否存在负环路. 
  
  vec_iter iter_forth_ = this->adjList_[iter_third_->first].cbegin();
  for(; iter_forth_ != this->adjList_[iter_third_->first].cend(); ++iter_forth_){
   
   if(this->distance_[*iter_forth_] > this->distance_[*iter_third_] + this->graph_[iter_third_->first][*iter_forth]){
    this->flag_ = true; //设为true表明存在负回路. 
    break;
   }
  }
  
  if(this->flag_){
   break;
  }
 }
 
}
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>
void Graph<T>::transition()noexcept
{
 Node<T> source_node(this->source_key_);
 map_iter iter = this->distance_.cbegin();
 for(; iter != this->distance_.cend(); ++iter){
  this->graph_[source_node][iter->first] = this->distance_[iter->first];
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::dijstra_algorithm(const Node<Ty>& node_)noexcept
{
 //注意这个+1,因为node_number_在初始化的时候被赋值为N.(N是不包含给定的源结点的,源结点是我们自己给出的不同于图中任何一个结点). 
 for(int i=1; i<this->node_number_+1; ++i){
  Node<T> temp_node = node_;
  int temp_weighting = ::MAXVALUE;
  
  vec_iter iter_ = this->adjList_[source_node].cbegin();
  for(; iter_ != this->adjList_[source_node].cend(); ++iter_){
   
   if(this->whether_visited_[*iter_] == false && this->graph_[source_node][*iter_] < temp_weighting){
    temp_weighting = this->graph_[source_node][*iter_];
    temp_node = *iter_;
   }
  }
  
  this->whether_visited_[source_node] = true; //已经访问过的结点被设置为true.
  
  mapVec_iter iter_first_ = this->adjList_.cbegin();
  for(; iter_first_ != this->adjList_cend(); ++iter_first_){
   this->relax_dijstra(iter_first->first, temp_node);
  }
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::relax_dijstra(const Node<Ty>& first_, const Node<Ty>& second_) //second----first想象成一条边. 
{
 if(this->whether_visited_[first_] == false && this->graph_[second_][first_] < ::MAXVALUE){
  
  if(this->distance_[second_] + this->graph_[second_][first_] < this->distance_[first_]){
   this->distance_[first_] = this->distance_[second_] + this->graph_[second_][first_];
   
   this->node_to_node_[first_] = second_; //first结点的前驱结点为second_; 
  }
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::johnson_algorithm(const Ty& source_)
{
 this->bellman_ford(0);
 if(this->flag_){
  throw std::runtime_error(std::string("There is negative-cycle in graph.\n"));
 }
 
 this->transiton(); //过渡函数. 
 
 mapVec_iter iter_first_ = this->adjList_.cbegin();
 for(; iter_first_ != this->adjList_.cend(); ++iter_first_){
  this->dijstra_algorithm(iter_first_->first);
  this->helper_function(iter_first_->first);
 }
}
template<typename T>
template<typename Ty>
void Graph<T>::helper_function(const Node<Ty>& node_)noexcept
{
 map_iter iter_first = this->distance_.cbegin();
 for(; iter_first != this->distance_.cend(); ++iter_first){
  Edge<Ty> temp_edge(node_, iter_first->first);
  temp_edge.weighting = iter_first->second;
  this->one_to_all_[node_].push_back(temp_edge);
 }
}

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/636440

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值