Dijkstra算法--图的最短路径

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


三、程序对应的图

对应的图



四、运行结果







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值