推免复习之数据结构与算法 迪杰斯特拉算法

知识常看常新,虽然之前在刷pat时也重新复习过迪杰斯特拉算法,但是当时的注意力主要还是集中在对题目的解决上,而不是对这个算法本身的理解上,所有我想重新写一篇文章,来记录这个算法。

迪杰斯特拉算法主要依靠的是贪心算法和BFS求最短路径,需要维护的数组共有四个,dist[]数组,pre[]数组,s[]数组和st[]数组。dist[]数组维护的是点v0到之后各点的最短路径长度;pre[]数组维护的是各节点的前驱节点,用来求到各点的最短路径,求最短路径需要使用回溯;s[]数组是目前已知节点的集合,探索到的顶点设置为true,没探索到到的顶点设置为false;st[]数组是顶点的全集减去s集合,所剩下的待探索的元素。

操作步骤如下:

(1) 初始时,s[]只包含起点v0;st[]包含除v0外的其他顶点,dist[0]设置为0,dist[i]=graph[0][i],也就是把dist数组初始化为距离矩阵中的点v0到该点的距离。

(2) 从st数组中选出dist值最小的顶点k,并将该顶点k加入到s数组中,同时,从st数组中移除顶点k。

(3) 更新dist中各个顶点到起点v0的距离。之所以更新dist中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(v0,v)的距离可能大于(v0,k)+(k,v)的距离。

(4) 重复步骤(2)和(3)一共n-1次,因为每循环一次就从st数组中取一个元素加入s数组,一共需要n-1次st数组才为空,此时遍历完所有顶点。

代码如下:

#include<iostream>
#include<vector>
using namespace std;

void InputGraph(vector<vector<int>> &graph)  //输入顶点之间的权值,否则为无限大
{
	int count = 0;
	cin >> count;
	for (int i = 0; i < count; i++)
	{
		int start = 0, end = 0,weight=0;
		cin >> start >> end>>weight;
		graph[start][end]= weight;
	}
}

void Dijkstra(vector<vector<int>> &graph,vector<int> &dist,vector<int> &pre)//计算最短路径
{
	int size = graph.size();
	dist=vector<int>(size);
	pre=vector<int> (size);
	vector<bool> s(size);
	vector<bool> ts(size);
	dist[0] = 0;
	pre[0] = -1;
	s[0] = true;
	ts[0] = false;
	for (int i = 1; i < size; i++)  //初始化数组
	{
		dist[i] = graph[0][i];
		s[i] = false;
		ts[i] = true;
	}

	for (int i = 0; i < size - 1; i++)  //共n-1次循环
	{
		int index = -1;
		int min = 999999;
		for (int i = 1; i < size; i++)
		{
			if (ts[i] == true && min >= dist[i])
			{
				index = i;
				min = dist[i];
			}
		}
		ts[index] = false;
		s[index] = true;
		for (int i = 1; i < size; i++)
		{
			if (dist[index] + graph[index][i] < dist[i])
			{
				dist[i] = dist[index] + graph[index][i];
				pre[i] = index;
			}
		}
	}
	cout << "结果如下所示:" << endl;
	for (int i = 1; i < size; i++)
	{
		cout << dist[i] << endl;
	}
	cout << endl;
	for (int i = 1; i < size; i++)
	{
		cout << pre[i] << endl;
	}
}

void getRoute(vector<int> &pre,int v)  //递归得到最短路径
{
	if (pre[v] == -1)
	{
		cout << 0;
		return;
	}
	else
	{
		getRoute(pre,pre[v]);
		cout << "->" << v ;
	}
}

int main()
{
	vector<vector<int>> input =vector<vector<int>>(5,vector<int>(5,999999));
	vector<int> dist;
	vector<int> pre;
	InputGraph(input);
	Dijkstra(input, dist, pre);
	for (int i = 1; i < 5; i++)
	{
		getRoute(pre, i);
		cout << "   dist=" << dist[i] << endl;
	}
	system("pause");
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值