Dijkstra算法的源代码

本篇博客是上一篇博客:Dijkstra最优路径算法及具体C++实例的源代码
https://blog.csdn.net/qq_40369246/article/details/86619696

main.cpp文件

#include<iostream>
#include "printHelp.h"

int main(){
    run();
}

printHelp.h文件

void run();

printHelp.cpp文件

#include<iostream>
#include "map.h"
#include "process.h"
using namespace std;

//打印菜单程序 
void printWindow(){
    cout<<"-----------------------------最优路径求解---------------------------------"<<endl<<endl;
    cout<<"**************************************************************************"<<endl<<endl;
    cout<<"---------------------------1.输入地图-------------------------------------"<<endl;
    cout<<"---------------------------2.打印地图-------------------------------------"<<endl;
    cout<<"---------------------------3.求解最优路径---------------------------------"<<endl;
    cout<<"---------------------------4.退出-----------------------------------------"<<endl<<endl;
    cout<<"**************************************************************************"<<endl<<endl; 
}

void run(){
    GraphMatrix graph;
    bool Initialize = false;
    printWindow();
    while(1){
    int Choice;
    cout<<"请输入你的选择:";
    cin>>Choice;
    if (Choice == 1){
        graph.createdGraph();
        if (graph.n() != NULL){
            Initialize = true;
        }
        system("pause");
    }else if(Choice == 2){
        if (Initialize == false){
            cout<<"未初始化有向图,请初始化有向图!!"<<endl;
        }else{
        graph.printGraph();
        }
        system("pause");
    }else if (Choice == 3){
        if (Initialize == false){
            cout<<"未初始化有向图,请初始化有向图!!"<<endl;
        }else{
        getBestRoute(&graph);
        }
        system("pause");
    }else if (Choice == 4){
        exit(1);
    }else{
        cout<<"无效输入,请重新输入!!!"<<endl;
        cin.clear();//清除错误状态
        cin.sync();//忽略掉输入缓冲区的数据
        system("pause");
    }
    system("cls");
    printWindow();
 } 
}

map.h文件

#include<string.h>

enum{
    VISITED, UNVISITED,
};

class GraphMatrix{
    public:
        ~GraphMatrix();
  
        void createdGraph();
        void printGraph();
  
        //输入定点数
        void inputVertexNumber(); 
        //生成定点数组 
        void makeVertexArray();
        //输入边数 
        void inputEdgeNumber();
        //输入边的信息 
        void inputEdgeInfo();
        //添加边结点至对应的链表中
        void addEdgeToList(int vFrom, int weight, int vTo); 
        //返回有向图的结点数 
        int n();
        //返回有向图的边数
        int e(); 
        //返回结点v的第一个相邻结点 
        int first(int v);
        //返回结点v在相邻结点w后的第一个邻结点 
        int next(int v, int w);
        //返回结点v1和v2之间的权重 
        int weight(int v1, int v2);
        //得到结点v是否被访问的标记
        int getMark(int v); 
        //设置结点是否被访问的标记 
        void setMark(int v, int val);
        //判断结点v1和v2间是否有边 
        bool isEdge(int v1, int v2);
        //存储有向图的路径 
        void setRoute(int v1, int v2, int val);
        //得到存储路径的矩阵中结点i与j之间的值
        int getRoute(int i, int j);
        //将字符串str转换为对应结点的整数 
        int ConvertInput(std::string str);
        //得到整数Node所对应的城市名称
        void CityName(int Node); 
        //进行一些防错机制的判断
        bool JudgeIsFalse(std::string str); 
  
    private:
        int m_vCount;
        int m_eCount;
        int** m_vVertex;//邻接矩阵
        int *mark;//标记结点是否已确定最短路径
        int** Route;//存储具体的路径
        std::string *City;//存储城市的名称
};

map.cpp文件

#include<iostream>
#include<iomanip>
#include<string.h>
#include<stdlib.h>
#include<sstream>
#include<fstream>
#include<vector>
#include<math.h>
using namespace std;

#define NO_EDGE 0
enum{
    VISITED, UNVISITED,
};

class GraphMatrix{
    public:
        ~GraphMatrix();
  
        void createdGraph();
        void printGraph();
  
        //输入定点数
        void inputVertexNumber(); 
        //生成定点数组 
        void makeVertexArray();
        //输入边数 
        void inputEdgeNumber();
        //输入边的信息 
        void inputEdgeInfo();
        //添加边结点至对应的链表中
        void addEdgeToList(int vFrom, int weight, int vTo); 
        //返回有向图的结点数 
        int n();
        //返回有向图的边数
        int e(); 
        //返回结点v的第一个相邻结点 
        int first(int v);
        //返回结点v在相邻结点w后的第一个邻结点 
        int next(int v, int w);
        //返回结点v1和v2之间的权重 
        int weight(int v1, int v2);
        //得到结点v是否被访问的标记
        int getMark(int v); 
        //设置结点是否被访问的标记 
        void setMark(int v, int val);
        //判断结点v1和v2间是否有边 
        bool isEdge(int v1, int v2);
        //存储有向图的路径 
        void setRoute(int v1, int v2, int val);
        //得到存储路径的矩阵中结点i与j之间的值
        int getRoute(int i, int j);
        //将字符串str转换为对应结点的整数 
        int ConvertInput(string str);
        //得到整数Node所对应的城市名称
        void CityName(int Node); 
        //进行一些防错机制的判断
        bool JudgeIsFalse(string str); 
  
 private:
  int m_vCount;
  int m_eCount;
  int** m_vVertex;//邻接矩阵
  int *mark;//标记结点是否已确定最短路径
  int** Route;//存储具体的路径
  string *City;//存储城市的名称
};

//实现上述具体的代码
int GraphMatrix::n(){
 return m_vCount;
}
int GraphMatrix::e(){
 return m_eCount;
}

int GraphMatrix::first(int v){
 for (int i = 0; i < m_vCount; i++){
  if(m_vVertex[v][i] != 0){
   return i;
  }
 }
 return m_vCount;
}
int GraphMatrix::next(int v, int w){
 for (int i = w+1; i < m_vCount; i++){
  if(m_vVertex[v][i] != 0){
   return i;
  } 
 }
 return m_vCount;
}

int GraphMatrix::weight(int v1, int v2){
 return m_vVertex[v1][v2];
}
int GraphMatrix::getMark(int v){
 return mark[v];
}
void GraphMatrix::setMark(int v, int val){
 mark[v] = val;
}
bool GraphMatrix::isEdge(int v1, int v2){
 return m_vVertex[v1][v2] != 0;
}
void GraphMatrix::setRoute(int v1, int v2, int val){
 Route[v1][v2] = val;
}
int GraphMatrix::getRoute(int i, int j){
 return Route[i][j];
}
GraphMatrix::~GraphMatrix(){
 for (int i = 0; i < m_vCount; i++){
  delete m_vVertex[i];
 }
 delete[] m_vVertex;
}

//一些其他有重要功能的函数
//构造邻接矩阵与路径矩阵
void GraphMatrix::makeVertexArray(){
 //构造邻接矩阵 
 m_vVertex = new int*[m_vCount];
 for (int i = 0; i < m_vCount; i++){
  m_vVertex[i] = new int[m_vCount];
 }
 for (int i = 0; i < m_vCount; i++){
  for (int j = 0; j < m_vCount; j++){
   m_vVertex[i][j] = NO_EDGE;
  }
 }
 
 //构造路径矩阵
 Route = new int*[m_vCount];
 for (int i = 0; i < m_vCount; i++){
  Route[i] = new int[m_vCount];
 }
 for (int i = 0; i < m_vCount; i++){
  for (int j = 0; j < m_vCount; j++){
   Route[i][j] = 0;
  }
 }
 
 //构造标记数组
 mark = new int[m_vCount];
 //构造城市数组
 City = new string[m_vCount];
 for (int i = 0; i < m_vCount; i++){
  City[i] = "";
 }
}

//输入结点的个数
void GraphMatrix::inputVertexNumber(){
 cout<<"Please input the number of vertexs.";
 m_vCount = 0;
 cin>>m_vCount;
 //以下为防输入的值数据类型错误的机制 
 if (m_vCount == 0){
  cout<<"输入的结点数值无效,请重新输入!!!!"<<endl;
  cin.clear();
  cin.sync();
 }
}
//输入边的数量
void GraphMatrix::inputEdgeNumber(){
 cout<<"Please input the number of edges.";
 m_eCount = 0;
 cin>>m_eCount;
 //以下为防输入的数据类型错误的机制
 if (m_eCount == 0){
  cout<<"输入的边数值无效,请重新输入!!!!"<<endl;
  cin.clear();
  cin.sync();
 } 
}

/*对字符串str进行转换: 如果str在城市数组City[i]中,则返回i; 如果str不在城市数组City中,就将str添加到City的未端City[j],再返回j; */
int GraphMatrix::ConvertInput(string str){
 int i;
 for (i = 0; (i < m_vCount) && (City[i] != ""); i++){
  if (City[i] == str){
   return i;
  }
 }
 City[i] = str;
 return i;
}
//打印整数Node所对应的城市名称
void GraphMatrix::CityName(int Node){
 if (City[Node] != ""){
  cout<<City[Node];
 }
}
//输入边的信息:起点、终点和权重
void GraphMatrix::inputEdgeInfo(){
 cout<<"Please input edge information:"<<endl;
 for (int i = 0; i < m_eCount; i++){
  cout<<"the edge"<<i<<":"<<endl;
  string start, end;
  
  //起点
  int from = 0;
  cout<<"From:";
  cin>>start;
  from = ConvertInput(start);//将边转化为对应的结点整数值,便于使用矩阵进行计算
  
  //权值
  int weight = 0;
  cout<<"Weight:";
  cin>>weight;
  if(weight == 0){
   cout<<"输入的距离数值无效,请重新输入!!!";
   cin.clear();//清除错误状态
   cin.sync();//忽略输入缓冲区的数据
   break; 
  }else{
   //终点
   int to = 0;
   cout<<"To:";
   cin>>end;
   to = ConvertInput(end);
   cout<<endl;
   
   addEdgeToList(from, weight, to); 
  }
 }
}

//将边添加到邻接矩阵中 
void GraphMatrix::addEdgeToList(int vFrom, int weight, int vTo){
 m_vVertex[vFrom][vTo] = weight;
}
//打印邻接矩阵
void GraphMatrix::printGraph(){
 for (int i = 0; i < m_vCount; i++){
  for (int j = 0; j < m_vCount; j++){
   cout<<setw(3)<<m_vVertex[i][j]<<" ";
  }
  cout<<endl;
 }
} 
/*一些防错设计: 判断结点数与边数是否正确; 判断字符串是否在城市数组中,被用于求解最优路径时防止输入的城市名称不存在 */
bool GraphMatrix::JudgeIsFalse(string str){
 if (str == "判断结点数与边数是否正确"){
  if (m_eCount > pow(m_vCount, 2)){
   cout<<"结点数与边数不正确,请重新输入。"<<endl;
   return false;
  }
  else{
   return true; 
  }
 }else{
  for (int i = 0; i < m_vCount; i++){
   if (str == City[i]){
    return true;
   }
  }
  return false;
 }
}

//创建一个有向图
void GraphMatrix::createdGraph(){
 inputVertexNumber();
 makeVertexArray();
 inputEdgeNumber();
 if (JudgeIsFalse("判断结点数与边数是否正确")){
  inputEdgeInfo();
 }
}

process.h文件

void InitD(GraphMatrix * G, int* D, int s);
void InitMark(GraphMatrix* G);
void InitRouteMatrix(GraphMatrix * G, int s);
int minVertex(GraphMatrix * G, int* D);
void Dijkstra(GraphMatrix * G, int* D, int s);
void getBestRoute(GraphMatrix * G);

process.cpp文件

#include<iostream>
#include "map.h"
using namespace std;

/* 对D[]进行初始化,D(s,v)为结点s与v之间的路径长度: D[s] = 0; s != v时,D[v] = weight(s,v); 当s与v间不存在时,D[v] = INT_MAX, INT_MAX为系统的正无穷。 */
void InitD(GraphMatrix * G, int * D, int StartNode){
 for (int i = 0; i < G->n(); i++){
  if (G->isEdge(StartNode, i)){
   D[i] = G->weight(StartNode, i);
  }else{
   D[i] = INT_MAX;
  }
 }
 D[StartNode] = 0;
}

//初始化标记矩阵
void InitMark(GraphMatrix* G){
 for (int i = 0; i < G->n(); i++){
  G->setMark(i, UNVISITED);
 }
}

/* 对路径矩阵进行初始化,初始化后如下图所示: s v1 -1 -1 ...... -1 s v2 -1 -1 ...... -1 .................... s vn -1 -1 ...... -1 */
void InitRouteMatrix(GraphMatrix * G, int StartNode){
 for (int i = 0; i < G->n(); i++){
  G->setRoute(i, 0, StartNode);
  G->setRoute(i, 1, i);
  for (int j = 2; j < G->n(); j++){
   G->setRoute(i, j, -1);
  }
 }
}

/* 得到一轮更新后的最短路径的结点: 最开始先找到一个未被访问过的结点v; 然后再用此结点与其它未被访问过的结点i一一比较,如果D[v]比D[i]大,则v = i; */
int minVertex(GraphMatrix * G, int* D){
 int i, Shortest = 0;
 for (i = 0; i < G->n(); i++){
  if(G->getMark(i) == UNVISITED){
   Shortest = i;
   break;
  }
 }
 for (i++; i < G->n(); i++){
  if ((G->getMark(i) == UNVISITED) && (D[i] < D[Shortest])){
   Shortest = i;
  }
 }
 return Shortest;
}

/* 利用Dijkstra求结点s与其余每个点间的最优路径,并将路径存入到路径矩阵中 */ 
void Dijkstra(GraphMatrix * G, int* Dis, int StartNode){
 int i, Shortest, w;
 InitD(G, Dis, StartNode);
 InitRouteMatrix(G, StartNode);//初始化路径矩阵
 InitMark(G);
 for (i = 0; i < G->n(); i++){
  Shortest = minVertex(G, Dis);
  if (Dis[Shortest] == INT_MAX) return;
  G->setMark(Shortest, VISITED);
  //如果新得到的s与w间的路径长度D[v]+weight(v,w) < 原路径D[w], 则更新D[w]的值
  for (w = G->first(Shortest); w < G->n(); w = G->next(Shortest, w)){
   if (Dis[w] > (Dis[Shortest] + G->weight(Shortest, w))){
    Dis[w] = Dis[Shortest] + G->weight(Shortest, w);
    //更新路径矩阵
    //每当从s到w有更短的路径时,就将s到w的路径更新为s到v的路径 + v到w的边
    int j;
    for (j = 0; (G->getRoute(Shortest, j) != -1) && (j < G->n()); j++){
     G->setRoute(w, j, G->getRoute(Shortest, j)); 
    }
    G->setRoute(w, j, w);
   }
  } 
 } 
}

//打印最短路径的具体路线
void getBestRoute(GraphMatrix * G){
 cout<<"可供选择的城市:"<<endl;
 for (int i = 0; i < G->n(); i++){
  G->CityName(i);
  cout<<" ";
 }
 cout<<endl;
 cout<<"请输入两个地点:"<<endl;
 string start, end;
 int v1, v2;
 int D[G->n()];//存储路径长度的数组
 cout<<"From:";
 cin>>start;
 cout<<"To:";
 cin>>end;
 
 if (!G->JudgeIsFalse(start)){
  cout<<"输入错误!!起点不存在"<<endl;
 }else if (!G->JudgeIsFalse(end)){
  cout<<"输入错误!!终点不存在"<<endl; 
 }else{
  v1 = G->ConvertInput(start);
  v2 = G->ConvertInput(end);
  Dijkstra(G, D, v1);
  if (D[v2] == INT_MAX){
   cout<<"不存在由"<<start<<"到"<<end<<"的路径。"<<endl; 
  }else{
   cout<<v1<<"到"<<v2<<"的最短路径长度为:"<<D[v2]<<endl;
   cout<<"路径为:";
   G->CityName(G->getRoute(v2, 0));
   for (int i = 1; (G->getRoute(v2, i) != -1) && (i < G->n()); i++){
    cout<<"-->";
    G->CityName(G->getRoute(v2, i));
   }
   cout<<endl;
  }
 }
}
    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_40369246/article/details/86651145
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞