本篇博客是上一篇博客: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;
}
}
}