Dijkstra算法(C/C++简明注释详解版: 代码实现 & 测试数据)

算法思想简述(From C知道):

Dijkstra算法是一种求解最短路径的贪心算法,它能够找到两点之间的最短路径。C语言实现Dijkstra算法需要以下步骤:

1. 创建一个数组用于记录起始点到其他节点的距离,初始化为无穷大。
2. 创建一个数组用于记录节点是否已经被访问过,初始化为false。
3. 将起始点到自身的距离设为0。
4. 遍历图中所有节点,对于每个节点:
   1) 找到起始点到该节点距离最短的节点(即未被访问过且距离最小的节点)。
   2) 标记该节点已经被访问过。
   3) 遍历该节点的所有邻居节点,更新起始点到邻居节点的距离。
5. 最终得到起始点到其他所有节点的最短距离。

dijkstra函数代码实现:

int n, m, s, e; // 节点数, 有向线段数, 起点, 终点
int graph[size][size]; // 图的邻接矩阵
int dist[size]; // 起点到各点的最短距离
bool visited[size]; // 记录节点是否被访问过

void dijkstra(int s)
{
	for(int i=1; i<=n; i++) // 初始化距离和访问状态
	{
		dist[i] = max;
		visited[i] = false;
	}
	dist[s] = 0; // 起点到自身的距离为0
	for(int i=1; i<=n; i++) // 遍历所有节点
	{
		int min = max, u = -1;
		for(int j=1; j<=n; j++) // 找到未访问节点中距离起点最近的节点
		{
			if(dist[j] < min && !visited[j])
			{
				u = j; min = dist[j];//可以用i=1的情况来理解,找到离原点最近的一个节点
			}
		}
		if(u == -1) return; // 若未找到可达节点,退出循环
		visited[u] = true; // 标记节点u为已访问
		for(int v=1; v<=n; v++) // 更新起点到各节点的距离
		{
			//从原点先到u再到v的路径 < 原先记录的从原点到v的路径	//u,v之间有通路
			if(dist[v] > dist[u] + graph[u][v] && !visited[v] && graph[u][v] != max) 
			{										//v尚未访问过
				dist[v] = dist[u] + graph[u][v];
			}
		}
	}
}

整体程序代码实现

#include<bits/stdc++.h> 
using namespace std; 
#define size 1000 // 定义图的最大节点数
#define max 1000000000 // 定义最大值
int n, m, s, e; // 节点数, 有向线段数, 起点, 终点
int graph[size][size]; // 图的邻接矩阵
int dist[size]; // 起点到各点的最短距离
bool visited[size]; // 记录节点是否被访问过

void dijkstra(int s)
{
	for(int i=1; i<=n; i++) // 初始化距离和访问状态
	{
		dist[i] = max;
		visited[i] = false;
	}
	dist[s] = 0; // 起点到自身的距离为0
	for(int i=1; i<=n; i++) // 遍历所有节点
	{
		int min = max, u = -1;
		for(int j=1; j<=n; j++) // 找到未访问节点中距离起点最近的节点
		{
			if(dist[j] < min && !visited[j])
			{
				u = j; min = dist[j];//可以用i=1的情况来理解,找到离原点最近的一个节点
			}
		}
		if(u == -1) return; // 若未找到可达节点,退出循环
		visited[u] = true; // 标记节点u为已访问
		for(int v=1; v<=n; v++) // 更新起点到各节点的距离
		{
			//从原点先到u再到v的路径 < 原先记录的从原点到v的路径	//u,v之间有通路
			if(dist[v] > dist[u] + graph[u][v] && !visited[v] && graph[u][v] != max) 
			{										//v尚未访问过
				dist[v] = dist[u] + graph[u][v];
			}
		}
	}
}

int main()
{
	cout<<"依次输入节点数, 有向线段数, 起点, 终点(数字间以空分隔): ";
	cin>>n>>m>>s>>e; // 输入节点数, 有向线段数, 起点, 终点
	for(int i=1; i<=n; i++) // 初始化图的邻接矩阵
	{
		for(int j=0; j<=n; j++)
		{
			graph[i][j] = i==j ? 0: max;
		} 
	}
	int u, v, wt;
	for(int i=1; i<=m; i++) // 输入有向线段的起点、终点和权重
	{
		cin>>u>>v>>wt;
		graph[u][v] = wt;
		graph[v][u] = wt; // 无向图,对称设置权重
	}
	dijkstra(s); // 调用Dijkstra算法求最短路径
	cout<<"min_track_length: "<<dist[e]; // 输出起点到终点的最短距离
	return 0;
}

送上测试数据一份:

/*
测试数据:
5 6 1 5
1 2 4
2 5 10
1 3 5
3 2 1
3 4 2
4 5 6
*/

~~ 希望对你有帮助 ~~

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dijkstra算法是一种用于解决单源最短路径问题的经典算法。下面是Dijkstra算法C++代码实现: ```cpp #include <iostream> #include <vector> #include <queue> #include <climits> using namespace std; // 定义图的邻接表表示 typedef pair<int, int> pii; typedef vector<vector<pii>> Graph; // Dijkstra算法实现 vector<int> dijkstra(const Graph& graph, int start) { int n = graph.size(); vector<int> dist(n, INT_MAX); // 存储起点到各个顶点的最短距离 vector<bool> visited(n, false); // 记录顶点是否已访问 priority_queue<pii, vector<pii>, greater<pii>> pq; // 小顶堆,存储顶点和距离的pair dist[start] = 0; // 起点到自身的距离为0 pq.push(make_pair(0, start)); while (!pq.empty()) { int u = pq.top().second; pq.pop(); if (visited[u]) { continue; } visited[u] = true; for (const auto& neighbor : graph[u]) { int v = neighbor.first; int weight = neighbor.second; if (dist[u] + weight < dist[v]) { dist[v] = dist[u] + weight; pq.push(make_pair(dist[v], v)); } } } return dist; } int main() { int n, m; // n为顶点数,m为边数 cin >> n >> m; Graph graph(n); for (int i = 0; i < m; ++i) { int u, v, weight; cin >> u >> v >> weight; graph[u].push_back(make_pair(v, weight)); graph[v].push_back(make_pair(u, weight)); } int start; cin >> start; vector<int> shortestDist = dijkstra(graph, start); for (int i = 0; i < n; ++i) { cout << "Shortest distance from " << start << " to " << i << " is " << shortestDist[i] << endl; } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值