dijkstra单源最短路径

执行过程

步骤

S集合中      

U集合中

1   

选入A,此时S ={A}

此时最短路径A->A = 0

A为中间点,从A开始找

U = {B, C, D, E, F}

A->B = 6

A->C = 3

A->U中其他顶点 = 

其中A->C = 3 权值为最小,路径最短

2

选入上一轮中找到的最短路径的顶点C,此时S = {A, C}

此时最短路径A->A = 0A->C = 3

C为中间点,从A->C=3这条最短路径开始新一轮查找

U = {B, D, E, F}

A->C->B = 5(比上面的A->B = 6要小)

替换B的权值为更小的A->C->B = 5

A->C->D = 6

A->C->E = 7

A->C->U中其他顶点 = 

其中A->C->B = 5 最短

3

选入B,此时S = {A, C, B}

此时最短路径 A->A = 0A->C = 3

A->C->B = 5

B为中间点,从A->C->B = 5这条最短路径开始新一轮查找

U = {D, E, F}

A->C->B->D = 10(比上面的A->C->D = 6大,不替换,保持D的权值为A->C->D=6)

A->C->B->U中其他顶点 = 

其中 A->C->D = 6 最短

4

选入D,此时 S = {A, C, B, D}

此时最短路径 A->A = 0A->C = 3A->C->B = 5A->C->D = 6

D为中间点,从A->C->D = 6这条最短路径开始新一轮查找

U = {E, F}

A->C->D->E = 8(比上面步骤2中的A->C->E = 7要长,保持E的权值为A->C->E =7)

A->C->D->F = 9

其中A->C->E = 7最短

5

选入E,此时 S = {A, C, B, D ,E}

此时最短路径 A->A = 0A->C = 3A->C->B = 5A->C->D = 6A->C->E =7,

E为中间点,从A->C->E = 7这条最短路径开始新一轮查找

U = {F}

A->C->E->F = 12(比第4步中的A->C->D->F = 9要长,保持F的权值为A->C->D->F = 9)

其中A->C->D->F =9最短

6

选入F,此时 S = {A, C, B, D ,E, F}

此时最短路径 A->A = 0A->C = 3A->C->B = 5A->C->D = 6A->C->E =7,A->C->D->F = 9

U集合已空,查找完毕

 

代码如下:

/*
 严蔚敏 dijkstra 算法

 D和min的变化	
0 5 3 6 7 MAX		min 3
0 5 3 6 7 MAX		min 5
0 5 3 6 7 9		min 6
0 5 3 6 7 9		min 7
0 5 3 6 7 9		min 9

*/
#include <iostream>
#include <cstdio>
#define MAX 999
using namespace std;
int arcs[10][10];//邻接矩阵
int D[10];//保存最短路径长度
int final[10];//若final[i] = 1则说明 顶点vi已在集合S中
int n = 0;//顶点个数
int v0 = 0;//源点
int v, w;
/* 若要求所有点到其它点的最短路径,只需要在函数中加一个形参N,然后初始化时D[i] = arcs[N][i]; 起初的final[N]=1;就ok了*/
void ShortestPath_DIJ()
{
	//初始化
	for (int i = 0; i < n; i++) 
	{
		D[i] = arcs[0][i];
		final[i] = 0;
	}
	final[0] = 1;
	for (int i = 0; i < n; i++)
	{
		int min = MAX;
		for (v = 0; v < n; v++)
		{		
			if (final[v] == 0)//点不在S中
			{	
				//找出与当前靠近的且权值最小的点
				if (D[v] < min)
				{
					w = v;
					min = D[v];
				}
			}
		}
		final[w] = 1;	//当前选出了一个点,加入集合s中
		//下面这个for的作用是更新最短路径
		for (int j = 0;j < n; j++)
		{
			if (final[j] == 0 && D[j]> min + arcs[w][j])
			{
				D[j] = min + arcs[w][j];
			}
		}
		//此处在第一次循环结束时,D[]里存放的最短路径已经更改了
	}
}
void Print();//输出邻接矩阵的函数声明
int main()
{
	n = 6;
	//若两点之间不可达则用MAX来代替
	int arry[36] = { 0,6,3,MAX,MAX,MAX,6,0,2,5,MAX ,MAX ,3,2,0,3,4,MAX ,MAX ,5,3,0,2,3,MAX ,MAX ,4,2,0,5,MAX ,MAX ,MAX ,3,5,0 };
	int idx = 0;
	for(int i=0;i<6;i++)
		for (int j = 0; j < 6; j++)
		{
			arcs[i][j] = arry[idx++];
		}
	Print();
	ShortestPath_DIJ();
	for (int i = 0; i < n; i++)
		printf("D[%d] = %d\n", i, D[i]);

	system("pause");
	return 0;
}
/*
D[0] = 0
D[1] = 5 
D[2] = 3 
D[3] = 6 
D[4] = 7 
D[5] = 9 
*/
void Print()
{
	cout << "邻接矩阵为: " << endl;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout.width(7);
			cout<< arcs[i][j];
		}
		cout << endl;
	}
}


以下是Dijkstra单源最短路径算法的Python实现: ```python import sys class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def printSolution(self, dist): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) def minDistance(self, dist, sptSet): min = sys.maxsize for v in range(self.V): if dist[v] < min and sptSet[v] == False: min = dist[v] min_index = v return min_index def dijkstra(self, src): dist = [sys.maxsize] * self.V dist[src] = 0 sptSet = [False] * self.V for cout in range(self.V): u = self.minDistance(dist, sptSet) sptSet[u] = True for v in range(self.V): if self.graph[u][v] > 0 and sptSet[v] == False and dist[v] > dist[u] + self.graph[u][v]: dist[v] = dist[u] + self.graph[u][v] self.printSolution(dist) # 测试 g = Graph(9) g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], [4, 0, 8, 0, 0, 0, 0, 11, 0], [0, 8, 0, 7, 0, 4, 0, 0, 2], [0, 0, 7, 0, 9, 14, 0, 0, 0], [0, 0, 0, 9, 0, 10, 0, 0, 0], [0, 0, 4, 14, 10, 0, 2, 0, 0], [0, 0, 0, 0, 0, 2, 0, 1, 6], [8, 11, 0, 0, 0, 0, 1, 0, 7], [0, 0, 2, 0, 0, 0, 6, 7, 0]] g.dijkstra(0) ``` 输出结果将会是: ``` Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14 ``` 这个实现中,我们创建了一个Graph类,其中包含了单源最短路径算法Dijkstra的实现。在测试中,我们创建了一个有9个节点的图,并使用Dijkstra算法计算从第0个节点到其他节点的最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值