#include <iostream>
#include <queue>
#include <map>
#include <stdexcept>//用于抛出异常.
#include <initializer_list> //std::initializer_list
namespace{ //用命名空间还是好的,防止命名污染.
static int MAXVALUE = 999;
}
template<typename T>
struct Node{
T node_;
int weighting_; //weighting_设置的是当前结点到给定源结点的所有的加权值的和默认都被设置为::MAXVALUE.
using node_type = T;
Node()=default;
template<typename Ty>
Node(const Ty& node, const int& weighting=0); //构造函数.
template<typename Ty>
Node(Node<Ty>&& otherNode); //移动构造函数.
Node(const Node<T>& otherNode); //拷贝构造函数.
Node<T>& operator=(const Node<T>& 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_);
template<typename Ty>
friend std::ostream& operator<<(std::ostream& os, const Node<Ty>& node_);
~Node()=default;//注意这里只是设置了默认构造函数
};
template<typename T>
template<typename Ty>
Node<T>::Node(const Ty& node, const int& weighting)
:node_(node),
weighting_(weighting)
{
//
}
template<typename T>
template<typename Ty>
Node<T>::Node(Node<Ty>&& otherNode)
:node_(otherNode.node_),
weighting_(otherNode.weighting_)
{
//
std::cout<<"move-constructor"<<std::endl;
}
template<typename T>
Node<T>& Node<T>::operator=(const Node<T>& otherNode)
{
this->node_ = otherNode.node_;
this->weighting_ = otherNode.weighting_;
//std::cout<<"operator="<<std::endl;
return *this;
}
template<typename T>
Node<T>::Node(const Node<T>& otherNode)
:node_(otherNode.node_),
weighting_(otherNode.weighting_)
{
//std::cout<<"copy for constructing"<<std::endl;
}
template<typename Ty>
bool operator<(const Node<Ty>& first_, const Node<Ty>& second_) //注意这里因为std::map是有序的切不重复容器.
{
return (first_.node_ < second_.node_) ? true : false;
}
template<typename Ty>
bool operator==(const Node<Ty>& first_, const Node<Ty>& second_)
{
return (first_.node_ == second_.node_) ? true : false;
}
template<typename Ty>
std::ostream& operator<<(std::ostream& os, const Node<Ty>& node_){
os<<node_.node_;
return os;
}
class Compare{
public:
template<typename Ty>
bool operator()(const Node<Ty>& first_, const Node<Ty>& second_);
};
template<typename Ty>
bool Compare::operator()(const Node<Ty>& first_, const Node<Ty>& second_)
{
return first_ < second_;
}
template<typename T>
class Graph{ //所有边的加权值必须为正.
private:
std::map<Node<T>, std::map<Node<T>, int>> edges_; //存储无向图的各个边的加权值.
std::map<Node<T>, std::vector<Node<T>>> adjList_; //每个结点所相接的结点的邻接链表.
std::map<Node<T>, bool> sourceArray_; //判断该点是否已经被放到了verticeArry_中.
std::map<Node<T>, int> dist_; //源结点到每个结点的距离.
std::map<Node<T>, Node<T>> node_to_node_;
template<typename Ty>
void initializer_distance(const Node<Ty>& source_)noexcept;
public:
template<typename Ty, unsigned int N>
Graph(const Ty (&edges)[N][3]);
template<typename Ty>
void Dijstra(const Ty& node_data);//Dijstra算法.
void print()const noexcept;
~Graph();
};
template<typename T>
template<typename Ty, unsigned int N>
Graph<T>::Graph(const Ty (&edges)[N][3])
{
if(N == 0){
std::runtime_error("There is nothing in Graph.\n");
}
for(int i=0; i<N; ++i){
Node<Ty> first_(edges[i][0], ::MAXVALUE);//这里之所以用::因为MAXVALUE位于匿名的namespace中.
Node<Ty> second_(edges[i][1], ::MAXVALUE);//每个结点当前的加权值被设置为MAXVALUE.
Node<Ty> temp_first_(edges[i][0], ::MAXVALUE);
if(edges[i][2] < 0){
throw std::runtime_error(std::string("The weighting must be bigger than 0"));
}
this->adjList_[first_].push_back(second_); //邻接链表.
this->dist_[first_] = ::MAXVALUE;
this->dist_[second_] = ::MAXVALUE;
this->sourceArray_[first_] = false;
this->sourceArray_[second_] = false;
for(int j=0; j<N; ++j){ //注意下面这几行这是为了构造一个结点的矩阵. 即每个结点与其他结点的之间的权重.
Node<Ty> temp_second_(edges[j][0], ::MAXVALUE);
if(temp_first_ == temp_second_){
this->edges_[temp_first_][temp_second_] = 0;
continue;
}
this->edges_[temp_first_][temp_second_] = ::MAXVALUE;
}
this->edges_[first_][second_] = edges[i][2];
}
std::cout<<"out of constructor."<<std::endl;
}
template<typename T>
template<typename Ty>
void Graph<T>::Dijstra(const Ty& node_data)
{
std::cout<<"enter dijstra"<<std::endl;
Node<Ty> source(node_data);
int node_number = this->adjList_.size();
this->initializer_distance(source); //获得从source到与source相接的结点的值.
for(int i=1; i<node_number; ++i){ //给定的图中一共有node_number个结点. 除去自身因此只需要循环node_number-1次.
Node<Ty> temp_node = source;
int temp_distance = ::MAXVALUE;
typename std::map<Node<Ty>, std::vector<Node<Ty>>>::const_iterator iter_first_ = this->adjList_.cbegin();
for(; iter_first_ != this->adjList_.cend(); ++iter_first_){ //这个循环访问图中的每一个结点与给定的源结点 保存当前邻接点中距离最小的一个结点.
if(this->sourceArray_[iter_first_->first] == false && this->dist_[iter_first_->first] < ::MAXVALUE){
temp_node = iter_first_->first;
temp_distance = this->dist_[iter_first_->first];
}
}
this->sourceArray_[temp_node] = true; //把已经找到的结点标记为true,标明已经访问过了.
//松弛操作.
typename std::map<Node<Ty>, std::vector<Node<Ty>>>::const_iterator iter_second_ = this->adjList_.cbegin();
for(; iter_second_ != this->adjList_.cend(); ++iter_second_){ //利用松弛操作,更新temp_node与其他各个结点之间权重.
if(this->sourceArray_[iter_second_->first] == false && this->edges_[temp_node][iter_second_->first] < ::MAXVALUE){
if(this->dist_[temp_node] + this->edges_[temp_node][iter_second_->first] < this->dist_[iter_second_->first]){
this->dist_[iter_second_->first] = this->dist_[temp_node] + this->edges_[temp_node][iter_second_->first];
this->node_to_node_[iter_second_->first] = temp_node;
}
}
}
}
}
template<typename T>
template<typename Ty>
void Graph<T>::initializer_distance(const Node<Ty>& source_)noexcept
{
typename std::vector<Node<Ty>>::const_iterator iter_ = this->adjList_[source_].cbegin();
for(; iter_ != this->adjList_[source_].cend(); ++iter_){ //dist_记录从source_到图中每个结点的距离.如果这两个结点没有相连接或者只有单向连接那么距离先被设置为::MAXVALUE;
this->dist_[*iter_] = this->edges_[source_][*iter_];
this->node_to_node_[*iter_] = source_; //把邻接source的结点都放到node_to_node中.
}
this->dist_[source_] = 0;
this->sourceArray_[source_] = true;
}
template<typename T>
Graph<T>::~Graph()
{
if(!this->edges_.empty()){
this->edges_.clear();
}
if(!this->adjList_.empty()){
typename std::map<Node<T>, std::vector<Node<T>>>::iterator iter = this->adjList_.begin();
for(; iter!=this->adjList_.end(); ++iter){
iter->second.clear();
}
this->adjList_.clear();
}
if(!this->sourceArray_.empty()){
this->sourceArray_.clear();
}
if(!this->dist_.empty()){
this->dist_.clear();
}
if(!this->node_to_node_.empty()){
this->node_to_node_.clear();
}
}
template<typename T>
void Graph<T>::print()const noexcept
{
typename std::map<Node<T>, Node<T>>::const_iterator iter = this->node_to_node_.cbegin();
for(; iter != this->node_to_node_.cend(); ++iter){
std::cout<<iter->first<<" "<<iter->second<<std::endl;
}
}
int main()
{
int undirectedGraph[9][3]={ {1, 6, 14}, {1, 3, 9}, {2, 3, 10}, {2, 4, 15}, {3, 6, 2}, {3, 4, 11}, {4, 5, 6}, {5, 6, 9}, {6, 9, 5} };
Graph<int> myGraph(undirectedGraph);
myGraph.Dijstra(1);
myGraph.print();
return 0;
}