算法笔记---Dijkstra算法

71 篇文章 0 订阅
41 篇文章 3 订阅

Dijkstra算法(读者可以将其读作“迪杰斯特拉算法”)用来解决单源最短路问题,给定图G和起点s,通过算法得到S到达其他每个顶点的最短距离。
算法基本思想:
1、对图G(V,E)设置集合S,存放已被访问的顶点。
2、每次从集合V-S中选择与起点s的最短距离最小的一个顶点(记为u),访问并加入集合S。
3、令顶点u为中介点,优化起点s与所有从u能到达的顶点v之间的最短距离。
4、这样的操作执行n次(n为顶点个数),直到集合S已包含所有顶点。

题目描述

图片来自于算法笔记

在这里插入图片描述
样例:

输入:
6 8 0//6个顶点,8条边,起点为0号。以下8行为8条边
0 1 1//边0->1的边权为1,下同
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
输出:
0 1 5 3 4 6

运行结果:

在这里插入图片描述

书中给出两种解决方法:
1、使用邻接矩阵来存储图的信息
2、使用邻接表来存储图的信息
上边两种算法只是在寻找最短路径的时候不同,其他的都相同

实际上,使用 stl 库中的priority_queue可以更快的求解,且时间复杂度为O(V*logV+E)

下面为代码:

#include<iostream>
#include<queue>
#include<vector>
#include<map>
#include<algorithm>
#include<limits.h>
#include<stack>
using namespace std;

const int dij_max_v = 101;

struct DijNode
{
	int id;//当前结点id
	int weight;//到该结点的权值
};

struct MinWeightCompare//小顶堆
{
	bool operator() (const DijNode node1, const DijNode node2) const{
		return node1.weight > node2.weight;
	}
};


//************************************
// Method:    dijkstra 返回单源最短路径
// FullName:  dijkstra
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: vector<DijNode> matrix[] 给定的图
// Parameter: DijNode start 初始结点
// Parameter: bool * visited 表示当前结点是否被访问
// Parameter: map<int,int> & parent 表示当前到结点的上一个结点
// Parameter: map<int,int> & distance 表示初始结点到当前结点的最短路径
//************************************
void dijkstra(vector<DijNode> matrix[], DijNode start, bool* visited, map<int, int>& parent, map<int, int>& distance) {
	priority_queue<DijNode, vector<DijNode>, MinWeightCompare> p_queue;//BFS 队列
	//该优先队列中的元素表示到当前结点的最短路径。
	p_queue.push(start);

	while (!p_queue.empty())
	{
		DijNode top_node = p_queue.top();
		p_queue.pop();
		visited[top_node.id] = true;//标记当前结点已被访问
		for (int i = 0;i < matrix[top_node.id].size();i++)
		{
			DijNode next_node = matrix[top_node.id][i];
			//当前结点没有被访问,且以 top_node 为中介点可以使得 next_node 更优
			if (visited[next_node.id] == false && distance[top_node.id] + next_node.weight < distance[next_node.id])
			{
				distance[next_node.id] = distance[top_node.id] + next_node.weight;
				DijNode node;
				node.id = next_node.id;
				node.weight = distance[next_node.id];//更新当前的最短距离
				p_queue.push(node);//将所遍历的结点加入到队列中
				parent[next_node.id] = top_node.id;//更新所遍历结点的父结点
			}
		}
	}
}

//打印start_node 到 end_node 的最短路径所经过的结点
void print_path(int start_node, int end_node, map<int, int>& parent) {
	stack<int> s;
	while (start_node != end_node)
	{
		s.push(end_node);
		end_node = parent[end_node];
	}
	while (!s.empty())
	{
		int result = s.top();
		s.pop();
		cout << result << " ";
	}
}


int main() {

	int n, m, s;//表示顶点个数,边数,初始结点
	cin >> n >> m >> s;
	int form_node, to_node, weight;//表示起始结点,终止结点,权值
	vector<DijNode> matrix[dij_max_v];//用来存放图
	DijNode node;

	map<int, int> parent;//存放当前结点的路径的上一个结点
	parent[s] = -1;//起始结点的父结点为 -1

	map<int, int> distance;//记录起始结点到其他结点的最短路径
	distance[s] = 0;//自己到自己的距离为 0 
	for (int i = 0;i < m;i++)
	{
		cin >> form_node >> to_node >> weight;
		node.id = to_node;
		node.weight = weight;
		matrix[form_node].push_back(node);
		if (to_node != s)
		{
			distance[to_node] = INT_MAX;//表示除了起始结点,剩下的皆为不可达
		}
	}
	
	bool visited[dij_max_v];
	fill(visited, visited + dij_max_v, false);
	node.id = s;//起始结点的id
	node.weight = 0;//起始结点距离自己的距离
	dijkstra(matrix, node, visited, parent, distance);
	//输出初始结点到每个结点的最短路径
	for (map<int,int>::iterator it = distance.begin();it != distance.end();it++)
	{
		cout << (*it).second << " ";
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值