Dijkstra算法--图的最短路径
一、源代码
dijkstra_self.cpp
/*
* dijkstra_self.cpp
*
* Created on: 2017年4月1日
* Author: @yinaibang
*
*
*
*Dijkstra算法步骤:
*
*a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},
* 初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},
* 若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为∞。
*
*b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
*
*c.以k为新考虑的中间点,修改U中各顶点的距离;
* 若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
*
*d.重复步骤b和c直到所有顶点都包含在S中。
*/
#include <iostream>
#include<fstream>
#include<cstring>
#include<errno.h>
using namespace std;
//两个节点之间不存在直接可达的边时,距离是∞,使用INF表示,INF取int的最大值
const int INF = (~(unsigned int) 0) / 2;
typedef struct Node {
char name[20]; //节点的名称
struct Node * preNode; //上一个节点
int weight; //权值,默认∞
int used; //是否已经在最短路径里面,1在,0不在,默认是0
} GNode, *PGNode;
typedef struct Graphy0 {
int **matrix; //邻接矩阵
PGNode *nodeArr; //节点数组
int vertexSum; //节点总数
} Graphy;
Graphy * graphy_init(const char *filename) {
FILE *pFile = freopen(filename, "r", stdin);
if (NULL == pFile) {
cout << strerror(errno) << endl;
return NULL;
}
//节点总数
int vertexSum = 0;
cin >> vertexSum;
//边总数
int edgeSum = 0;
cin >> edgeSum;
//节点数组的构造和初始化
PGNode * vNodeArr = new PGNode[vertexSum];
for (int i = 0; i < vertexSum; i++) {
PGNode pGNode = new GNode();
pGNode->used = 0;
pGNode->preNode = NULL;
pGNode->weight = INF;
vNodeArr[i] = pGNode;
}
//邻接矩阵的构造和初始化
int **matrix = new int*[vertexSum];
for (int i = 0; i < vertexSum; i++) {
matrix[i] = new int[vertexSum];
for (int j = 0; j < vertexSum; j++) {
matrix[i][j] = INF;
}
}
// 从文本文件读取节点名称
for (int i = 0; i < vertexSum; i++) {
cin >> vNodeArr[i]->name;
}
//从文本文件读取邻接矩阵
int x = 0;
int y = 0;
int edgeLen = 0;
for (int i = 0; i < edgeSum; i++) {
cin >> x >> y >> edgeLen;
matrix[x][y] = matrix[y][x] = edgeLen;
}
//图的构造和初始化
Graphy *pGraphy = new Graphy();
pGraphy->matrix = matrix;
pGraphy->nodeArr = vNodeArr;
pGraphy->vertexSum = vertexSum;
return pGraphy;
}
//显示从文件文件读取的树的节点名称和邻接矩阵
void graphy_show(Graphy *pGraphy) {
if (NULL == pGraphy) {
return;
}
PGNode* nodeArr = pGraphy->nodeArr;
int** matrix = pGraphy->matrix;
cout << endl;
cout << "节点信息:\n";
for (int i = 0; i < pGraphy->vertexSum; i++) {
cout << nodeArr[i]->name << "," << nodeArr[i]->used << "," << nodeArr[i]->weight << "," << endl;
}
cout << endl << endl;
cout << "邻接矩阵:\n";
for (int i = 0; i < pGraphy->vertexSum; i++) {
for (int j = 0; j < pGraphy->vertexSum; j++) {
if (matrix[i][j] == INF) {
cout << "INF,\t";
} else {
cout << matrix[i][j] << ",\t";
}
}
cout << endl;
}
cout << endl;
}
/**
* 计算最短路径
* @startIndex,出发节点在节点数组中的下标,从0开始
*/
void graphy_process_shortestPath(Graphy * pGraphy, int startIndex) {
if (NULL == pGraphy) {
return;
}
//出发点的初始化
PGNode* nodeArr = pGraphy->nodeArr;
PGNode pStartNode = nodeArr[startIndex];
pStartNode->used = 1;
pStartNode->weight = 0;
int** matrix = pGraphy->matrix;
PGNode pCurGNode = pStartNode;
int curIndex = startIndex;
// cout << pCurGNode->name << "进入S中" << endl;
int vertexSum = pGraphy->vertexSum;
while (pCurGNode) {
int minLen = INF;
int tmpIndex = -1;
for (int i = 0; i < vertexSum; i++) {
int used = nodeArr[i]->used;
//如果不存在关联的边,直接下一次循环
if (1 == used) {
continue;
}
//边关联的时候
int edgeLen = matrix[curIndex][i];
if (edgeLen < INF) {
int newDistance = pCurGNode->weight + edgeLen;
if (newDistance < nodeArr[i]->weight) {
nodeArr[i]->weight = newDistance;
nodeArr[i]->preNode = pCurGNode;
}
}
if (nodeArr[i]->weight < minLen) {
minLen = nodeArr[i]->weight;
tmpIndex = i;
}
}
if (-1 == tmpIndex) {
break;
}
curIndex = tmpIndex;
nodeArr[curIndex]->used = 1;
pCurGNode = nodeArr[curIndex];
// cout << pCurGNode->name << "进入S中" << endl;
}
}
void graphy_show_shortestPath(Graphy *pGraphy, int startIndex) {
if (NULL == pGraphy) {
return;
}
PGNode* nodeArr = pGraphy->nodeArr;
PGNode pCurGNode = NULL;
PGNode statck[pGraphy->vertexSum];
for (int i = 0; i < pGraphy->vertexSum; i++) {
pCurGNode = nodeArr[i];
cout << nodeArr[startIndex]->name << " to reach " << pCurGNode->name << ",shortest path length:" << pCurGNode->weight << "\t:\t";
//把每个节点放到栈中
int stackIndex = 0;
while (pCurGNode) {
statck[stackIndex] = pCurGNode;
pCurGNode = pCurGNode->preNode;
stackIndex++;
}
//把栈中内容逐个弹出
int maxStackIndex = stackIndex - 1;
for (int i = maxStackIndex; i >= 0; i--) {
cout << statck[i]->name;
if (i > 0) {
cout << " --> ";
}
}
cout << endl;
}
}
void graphy_destroy(Graphy *pGraphy) {
if (NULL == pGraphy) {
return;
}
int** matrix = pGraphy->matrix;
PGNode* nodeArr = pGraphy->nodeArr;
int vertexSum = pGraphy->vertexSum;
for (int i = 0; i < vertexSum; i++) {
delete matrix[i];
}
delete matrix;
for (int i = 0; i < vertexSum; i++) {
delete nodeArr[i];
}
delete nodeArr;
delete pGraphy;
}
int main() {
const char *filename = "input.txt";
Graphy *pGraphy = graphy_init(filename);
graphy_show(pGraphy);
int startIndex = 0; //出发点的索引,从0开始
graphy_process_shortestPath(pGraphy, startIndex);
graphy_show_shortestPath(pGraphy, startIndex);
graphy_destroy(pGraphy);
return 0;
}
二、源代码需要的文件文件
注意:需要的文本文件的名称为input.txt,内容如下
5
7
A1
B2
C3
D4
E5
0 1 10
0 3 30
0 4 100
1 2 50
2 4 10
3 2 20
3 4 60
三、程序对应的图
对应的图
四、运行结果
因篇幅问题不能全部显示,请点此查看更多更全内容