Dijkstra求单源最短路径

本文详细介绍Dijkstra算法原理及其C++实现过程,适用于求解带权有向图的单源最短路径问题。通过实例演示了如何利用优先队列优化算法效率,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:Dijkstra求解带权有向图的单源最短路径问题。与Bellman-Ford算法的区别是要求图中没有负的权值边。在这种情况下Dijkstra算法通常有比较好的复杂度。特别是使用堆以后。算法维护一个点集S,该集合中的结点的最短路径已经求出,算法重复从结点集V-S中选择最短路径估计最小的结点,将其加入S中,并该结点出发的所有边进行松弛。

代码:

// dijkstra.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <queue>
#include <fstream>
#include <stack>

#define MAX 100
#define INF 1000000
#define DIS(a) (dis[a])

using std::cin;
using std::cout;
using std::endl;
using std::cerr;
using std::priority_queue;
using std::ifstream;
using std::stack;

typedef struct Edge {
	int u;
	int v;
	int val;
};


class mycomparison
{
	int dis[MAX];
public:
	mycomparison(int a[MAX], int n)
	{
		for (int i = 0; i < n; i++)
			dis[i] = a[i];
	}

	bool operator() (const int &a, const int &b) const
	{
		return dis[a] > dis[b];
	}
};

//对边(u,v)的松弛操作
void relax(int u, int v, int pre[MAX], int dis[MAX], int a[MAX][MAX])
{
	if (dis[v] > dis[u] + a[u][v])
	{
		dis[v] = dis[u] + a[u][v];
		pre[v] = u;
	}
}

void dijkstra(int a[MAX][MAX], int vertex_num, int edge_num, int dis[MAX], int pre[MAX])
{
	typedef priority_queue<int, std::vector<int>, mycomparison> mypq_type;
	mypq_type Q(mycomparison(dis, vertex_num));
	for (int i = 0; i < vertex_num; i++) //初始化优先级队列
		Q.push(i); 

	while (!Q.empty())
	{
		int temp = Q.top();
		Q.pop();
		for (int i = 0; i < vertex_num; i++)
		{
			if (a[temp][i] != INF)
				relax(temp, i, pre, dis, a);
		}
	}
}

//重构路径
void reconstruct(int i, int pre[MAX], stack<int> &s)
{
	if (pre[i] == -1) //边界情况,重构源结点
	{
		s.push(i);
		return;
	}

	s.push(i); //加入本结点
	while (pre[i] != -1)
	{
		s.push(pre[i]);
		i = pre[i];
	}

}

int main()
{
	ifstream in;
	in.open("dijkstra测试数据.txt");

	int vertex_num, edge_num; //点数,边数
	in >> vertex_num >> edge_num;

	int a[MAX][MAX]; 
	for (int i = 0; i < vertex_num; i++) //初始化邻接矩阵
		for (int j = 0; j < vertex_num; j++)
			a[i][j] = INF;

	int u, v, val;
	for (int i = 0; i < edge_num; i++)
	{
		in >> u >> v >> val;
		a[u][v] = val;
	}

	int dis[MAX]; //最短路径权重
	for (int i = 0; i < vertex_num; i++)
		dis[i] = INF;

	int pre[MAX]; //前驱结点
	for (int i = 0; i < vertex_num; i++)
		pre[i] = -1;

	dis[0] = 0;

	dijkstra(a, vertex_num, edge_num, dis, pre);
	stack<int> s; //用于重构路径

	for (int i = 0; i < vertex_num; i++)
	{
		cout << dis[i] << endl << "route: ";

		reconstruct(i, pre, s);
		while (!s.empty())
		{
			int temp = s.top();
			cout << temp << " ";
			s.pop();
		}
		cout << endl;
	}

	system("pause");
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值