Dijkstra算法 最短路径

叙述

今天终于写到著名的贪心算法——Dijkstra算法了,内心有点激动。

  • 小明的故事

    Dijstra算法对很多人来说看起来比较困难,不是很能理解,其实也没什么啦!
    比如,小明要自己驾车从科技大学去博物馆,考虑到利益上涨油价以及一贫如洗的口袋,小明不能那么任性,来一场说走就走的旅行,所以小明开始像屌丝一样精打细算,寻找一条最短的路径以结束那些不必要的花费。你掏出地图,认真的比较到博物馆去的各种路线,但及其复杂的路网让小明眼花缭乱,一时半会找不到最节省的路线,内心很是烦躁,此时此刻小明掏出口袋里的白将军,狠狠地吸上一口,突然一道光从脑子里闪出来,很快就找到了最短路径。
    在这里插入图片描述

  • 小明是怎么实现的呢?
    小明想我能不能先找到距离科技大学最近的地标,然后再以这个地标为起点,寻找下一个距离最近的地标,循序渐进,直到找到目的地。因为每次找到的距离都是最近的,所以从始发地到目的地累加起来的距离也是最近的。果然是一个好主意,激动的小明把没抽完的半根白将军狠狠的扔在地上,并用脚摩擦了几下,开始寻找最短路径,很快就找了理想的路线。

  • 小明的灿烂人生
    计算机出身的小明回去以后很快发现了商机,通过自己的聪明才智,开发出了地图软件,挣了好大一笔钱,并用这笔钱投资了国内最大的单身交友平台—CSDN,成为了CSDN的老板,过上了幸福美满的生活。

代码实现

	/*
	Dijkstra的思路就是:
	找到与源点权值最小的边,然后再此边找到到其他顶点的最小的边,依次类推,每次找到的都是最小的边
	最后所得的最短路径长度就是各最小边的和
	*/
	
	#include<iostream>
	#include<string>
	#include<stack>
	using namespace std;
	
	#define OK 1
	#define ERROR 0
	#define MAXint 32767 //表示无穷大
	#define MVNum 100	//最大顶点数
	
	//邻接矩阵的结构
	typedef struct
	{
    
    
		string vexs[MVNum];//顶点表
		int arcs[MVNum][MVNum];//邻接矩阵,也就是表示边的权值
		int vexnum, arcnum;//图的顶点数和边的个数
	}AMGraph;
	//邻接矩阵的结构
	
	//Dijstra结构
	bool S[MVNum] = {
    
     false };//记录从源点到终点是否已被确定最短路径长度
	int Path[MVNum] = {
    
     -1 };//记录终点的直接前驱序号
	int D[MVNum];//记录最短路径长度
	//Dijstra结构
	
	
	//查询结点位置
	int Locate(AMGraph G, string v)
	{
    
    
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			if (G.vexs[i] == v)
			{
    
    
				return i;
			}
		}
		return -1;
	}
	//查询结点位置
	
	//创建邻接矩阵
	int CreateUDN(AMGraph& G)//无向图的构造
	{
    
    
		cout << "请输入图的顶点数和边数:";
		cin >> G.vexnum >> G.arcnum;
		cout << "请输入各点的信息:";
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			cin >> G.vexs[i];
		}
		for (int i = 0; i < G.vexnum; i++)//初始化边的权值为MAXINT
		{
    
    
			for (int j = 0; j < G.vexnum; j++)
			{
    
    
				G.arcs[i][j] = MAXint;
			}
		}
		cout << "各边的顶点信息和权值:";
		for (int k = 0; k < G.arcnum; k++)//构造邻接矩阵
		{
    
    
			string v1, v2;
			int w;//边的两个顶点以及权值
			cin >> v1 >> v2 >> w;
			int i = Locate(G, v1);//找到点的位置
			int j = Locate(G, v2);
			G.arcs[i][j] = w;//赋予权值
			//G.arcs[j][i] = G.arcs[i][j];
		}
		return OK;
	}
	//创建邻接矩阵
	
	
	//Dijksta
	void ShortestPath_DIJ(AMGraph G, int v)
	{
    
    
		int n = G.vexnum;//图的节点的数量
		for (int i = 0; i < n; i++)
		{
    
    
			D[i] = G.arcs[v][i];
			if (D[i] < MAXint)
			{
    
    
				Path[i] = v;
			}
			else
			{
    
    
				Path[i] = -1;
			}
		}
		S[v] = true;//初始化v已有最短路径
		D[v] = 0;//最短路径为0
		for (int i = 1; i < n; i++)
		{
    
    
			int min = MAXint;
			for (int j = 0; j < n; j++)//找到与v邻接的边的权值最小的
			{
    
    
				if (!S[j] && D[j] < min)
				{
    
    
					v = j;
					min = D[j];
				}
			}
			S[v] = true;//找到最短路径
			for (int k = 0; k < n; k++)//更新从v出发到各顶点的最短路径长度
			{
    
    
				if (!S[k] && (D[v] + G.arcs[v][k]) < D[k])
				{
    
    
					D[k] = D[v] + G.arcs[v][k];//更新最短路径长度
					Path[k] = v;//更改k的前驱为v
				}
			}
		}
	}
	//Dijksta
	
	//显示最短路径
	void ShowShortTest(AMGraph G, string v)
	{
    
    
		int s = Locate(G,v);//定位
		ShortestPath_DIJ(G, s);
		for (int i = 0; i < G.vexnum; i++)
		{
    
    
			stack<string> sta;//引入栈
			if (i != s && Path[i] != -1)
			{
    
    
				sta.push(G.vexs[i]);
				int path = Path[i];
				while (path != -1)
				{
    
    
					sta.push(G.vexs[path]);
					path = Path[path];
				}
			}
			if (!sta.empty())
			{
    
    
				cout << sta.top();
				sta.pop();
			}
			while (!sta.empty())
			{
    
    
				cout << "->";
				cout << sta.top();
				sta.pop();
			}
	
			if (i != s && Path[i] != -1)
			{
    
    
				cout << " 最短路径长度为:" << D[i];
				cout << endl;
			}
		}
	
	}
	//显示最短路径
	
	int main()
	{
    
    
		AMGraph G;
		CreateUDN(G);
		string v;
		cout << "请输入起点:";
		cin >> v;
		ShowShortTest(G, v);
		return 0;
	}
	/*
	v0 v1 v2 v3 v4 v5
	各边的顶点信息和权值:v1 v2 5 v2 v3 50 v0 v2 10 v0 v4 30 v4 v3 20 v3 v5 10 v0 v5 100 v4 v5 60
	*/

猜你喜欢

转载自blog.csdn.net/m0_43456002/article/details/104382960
今日推荐