实现有向图的Dijkstra最短路径算法

实现有向图的Dijkstra最短路径算法,输入起始顶点Vi和终止顶点Vj,输出从Vi到Vj的最短路径及其长度。
在此基础上,借助OpenCV将图及其上从Vi到Vj的最短路径画出来。函数Dijkstra()  ->  源文件Dijkstra.cpp

效果图如下

 

input.txt内容如下

1 2 10
1 6 8
2 1 10
2 3 12
2 4 15
3 2 12
3 5 6
4 2 15
4 5 7
5 3 6
5 4 7
6 1 8
6 7 5
6 8 20
7 6 5
7 8 14
8 6 20
8 7 14
7 9 5
9 10 9
10 9 9

代码如下:代码段中有详细注释

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <iostream>
#include<math.h>
#include<stdlib.h>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
/*第11次数据结构作业
(1) 实现有向图的Dijkstra最短路径算法,输入起始顶点Vi和终止顶点Vj,输出从Vi到Vj的最短路径及其长度。
在此基础上,借助OpenCV将图及其上从Vi到Vj的最短路径画出来。函数Dijkstra()  ->  源文件Dijkstra.cpp
(2) 实现有向图的拓扑排序和关键路径算。在此基础上,借助OpenCV将图及其关键路径画出来。函数CriticalPath() -> 源文件CriticalPath.cpp*/
Mat P(600, 800, CV_8UC3, Scalar(255, 255, 255));
int a[50], b[50], c[50];//初始化时用的初始点 终点 权值
int distances[15];//初始点到其他各点的距离
int route[10];//每个节点最短路径的前驱
int found[10];//标识该节点是否找到最短路径
#define MAX_DATA 9999
struct datas//点的颜色
{
	int r, g, b;
}color[11];
struct location//点的位置
{
	int x, y;
}local[11];

void startdata()//颜色 坐标初始值
{
	int i;
	for (i = 1; i < 11; i++)
	{
		color[i].r = rand() % 255;
		color[i].b = rand() % 255;
		color[i].g = rand() % 255;
	}
	local[1].x = 400; local[1].y = 50; local[2].x = 280; local[2].y = 100; local[3].x = 170; local[3].y = 200; local[4].x = 330; local[4].y = 200;
	local[5].x = 240; local[5].y = 320; local[6].x = 500; local[6].y = 110; local[7].x = 510; local[7].y = 250; local[8].x = 600; local[8].y = 250;
	local[9].x = 520; local[9].y = 400; local[10].x = 650; local[10].y = 400;
}
int seek()// 寻找当前最小的路径 在未获取最短路径的顶点中,找到离i最近的顶点u
{
	int i, min=MAX_DATA, min_position=-1;
	for (i = 0; i < 10; i++)
	{
		if (distances[i] < min && !found[i])
		{
			min = distances[i];
			min_position = i;
		}
	}
	return min_position;
}
void Dijkstra(int v, int t,int cost[][15], int n)//Dijkstra最短路算法
{
	int i, u, w; 
	int temp[10] = { 0 };
	for (i = 1; i <= n; i++)//初始化
	{
		found[i] = 0;//顶点i的最短路径还未得到
		distances[i] = cost[v][i];// 初始化顶点i的最短路径为顶点v到顶点i的权
		route[i] = 1;//初始化顶点i的前驱顶点为1
	}
	found[v] = 1;//初始点的最短路径已经得到
	distances[v] = 0;//初始点v的最短路径为0
	for (i = 0; i < n-1; i++)
	{
		u = seek(); // 寻找当前最小的路径 在未获取最短路径的顶点中,找到离i最近的顶点u
		found[u] = 1; // 标记顶点u为已经获取到最短路径
		for(w=1;w<=n;w++)// 修正当前最短路径和前驱顶点.即当已经顶点k的最短路径之后,更新未获取最短路径的顶点的最短路径和前驱顶点
		{ 
			if(!found[w]&& distances[u] + cost[u][w] < distances[w])
				{
					route[w] = u;//顶点w的前驱设置为u
					distances[w] = distances[u] + cost[u][w];//更新该顶点的最短路径
				}
		}
	}
	while (t != v)//根据前驱点画出最短路径
	{
		line(P, Point(local[t].x, local[t].y), Point(local[route[t]].x, local[route[t]].y), Scalar(0, 0, 255), 5, CV_AA);
		imshow("out", P);
		waitKey(20);
		t = route[t];
	}
	imwrite("Dijkstra.png", P);
}
int main()
{
	startdata();
	FILE *fp; int cost[15][15];
	fopen_s(&fp, "input.txt", "r");
	int i = 0, sum = 0;
	while (!feof(fp))
	{
		fscanf_s(fp, "%d %d %d\n", &a[i], &b[i], &c[i]);
		i++; sum++;
	}
	fclose(fp);
	for (i = 0; i < sum; i++)
	{
		Point s;
		circle(P, Point(local[a[i]].x, local[a[i]].y), 40, Scalar(color[a[i]].r, color[a[i]].g, color[a[i]].b), -1);
		circle(P, Point(local[b[i]].x, local[b[i]].y), 40, Scalar(color[b[i]].r, color[b[i]].g, color[b[i]].b), -1);
		line(P, Point(local[a[i]].x, local[a[i]].y), Point(local[b[i]].x, local[b[i]].y), Scalar(0, 0, 0), 5, CV_AA);
		imshow("out", P);
		waitKey(20);
	}
	for (i = 0; i < 15; i++)
		for (int j = 0; j < 15; j++)
		{
			cost[i][j] = MAX_DATA;
		}
	for (i = 0; i < sum; i++)
	{
		cost[a[i]][b[i]] = c[i];
	}
	Dijkstra(1,10, cost, 10);
	for (i = 1; i <= 10; i++)
		printf("%d ", distances[i]);
}

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是Dijkstra最短路径算法的C++实现。假设我们有一个无向图,节点编号为0到n-1,图的邻接矩阵为graph。 ```c++ #include <iostream> #include <vector> #include <queue> #include <limits.h> // for INT_MAX using namespace std; // Dijkstra最短路径算法 void Dijkstra(vector<vector<int>>& graph, int start) { int n = graph.size(); // 存储每个节点的最短路径 vector<int> dist(n, INT_MAX); // 起点到起点的距离为0 dist[start] = 0; // 存储已经处理过的节点 vector<bool> visited(n, false); // 优先队列,按照距离排序 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 把起点加入队列 pq.push({0, start}); while (!pq.empty()) { // 取出队首节点 int u = pq.top().second; pq.pop(); // 如果已经处理过,跳过 if (visited[u]) continue; // 标记为已处理 visited[u] = true; // 更新相邻节点的最短路径 for (int v = 0; v < n; ++v) { // 如果节点v未处理过,且u到v有边 if (!visited[v] && graph[u][v]) { // 如果通过u到v的距离更短 if (dist[u] + graph[u][v] < dist[v]) { // 更新最短路径 dist[v] = dist[u] + graph[u][v]; // 把节点加入队列 pq.push({dist[v], v}); } } } } // 输出最短路径 for (int i = 0; i < n; ++i) { cout << "Start " << start << " to " << i << " : " << dist[i] << endl; } } int main() { // 无向图的邻接矩阵 vector<vector<int>> graph = { {0, 1, 4, 0, 0}, {1, 0, 2, 7, 0}, {4, 2, 0, 3, 5}, {0, 7, 3, 0, 2}, {0, 0, 5, 2, 0} }; Dijkstra(graph, 0); return 0; } ``` 这个算法的时间复杂度为O(nlogn),其中n为节点数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值