图——单源最短路径(Dijkstra算法)

从某个源点到其他顶点的最短路径。

严版数据结构P189 算法7.15
IDE:VS2015

#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<limits.h>
#include<iomanip>

using namespace std;

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define INFINITY 32767 //最大值
#define MAX_VERTEX_NUM 20 //最大顶点个数
typedef int Status;
typedef int VRType;
typedef int InfoType;
typedef bool** PathMatrix;


//{有向图,有向网,无向图,无向网}
typedef enum { DG, DN, UDG, UDN }GraphKind;

typedef struct ArcCell {
	VRType adj;//VRType是顶点关系类型。对无权图,用1或0
			   //表示相邻否;对带权图,则为权值类型
	InfoType *info;//该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef ArcCell* ShortPathTable;
typedef char VertexType;
typedef struct {
	VertexType vexs[MAX_VERTEX_NUM];//顶点向量
	AdjMatrix arcs;//邻接矩阵
	int vexnum, arcnum;//图的当前顶点数和弧数
	GraphKind kind;//图的种类标志
}MGraph;




//在G中找到v对应的顶点位置
int LocateVex(MGraph G, char v)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vexs[i] == v)
		{
			return i;
		}
	}
	return -1;
}



Status CreateDN(MGraph &G)
{
	int i, j, k, w;
	VertexType v1, v2;
	cout << "输入顶点数G.vexnum:";
	cin >> G.vexnum;
	cout << "输入边数G.arcnum:";
	cin >> G.arcnum;
	getchar();
	for (i = 0; i < G.vexnum; i++)
	{
		cout << "输入顶点G.vexs[" << i << "]" << endl;
		cin >> G.vexs[i];
		getchar();
	}//构造顶点向量

	 //初始化邻接矩阵
	for (i = 0; i < G.vexnum; i++)
	{
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j].adj = INFINITY;
			G.arcs[i][j].info = NULL;
		}
	}
	//构造邻接矩阵
	for (k = 0; k < G.arcnum; ++k)
	{
		cout << "输入第" << k + 1 << "条边vi、vj和权值w(int):" << endl;
		//输入一条边依附的顶点及权值
		cin >> v1;
		cin >> v2;
		cin >> w;
		getchar();
		//确定v1和v2在G中的位置
		i = LocateVex(G, v1);
		j = LocateVex(G, v2);
		G.arcs[i][j].adj = w;//弧<v1,v2>的权值
	}
	return OK;
}

void list(MGraph G)
{
	int i, j;
	cout << "输出邻接矩阵:" << endl;
	for (i = 0; i < G.vexnum; ++i)
	{
		cout << G.vexs[i] << "----";
		for (j = 0; j < G.vexnum; ++j)
		{
			if (G.arcs[i][j].adj == INFINITY)
				cout << setw(4) << "∞";
			else
				cout << setw(4) << G.arcs[i][j].adj;
		}
		cout << endl;
	}
}

void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D)
{
	int i, j, v, w;
	P = (bool **)malloc(sizeof(bool *)*G.vexnum);
	for (int i = 0; i < G.vexnum; i++)
		P[i] = (bool *)malloc(sizeof(bool)*G.vexnum);
	D = (ArcCell *)malloc(sizeof(ArcCell)*G.vexnum);

	bool *final = new bool[G.vexnum];

	for (v = 0; v < G.vexnum; ++v)
	{
		final[v] = FALSE;
		D[v] = G.arcs[v0][v];
		for (w = 0; w < G.vexnum; ++w)
		{
			P[v][w] = FALSE;
		}
		if (D[v].adj < INFINITY)
		{
			P[v][v0] = TRUE;
			P[v][v] = TRUE;
		}
	}//for

	int min;
	//初始化,v0顶点属于S集
	D[v0].adj = 0; final[v0] = TRUE;
	//开始主循环,每次求得v0到某个顶点的最短路径,并加v到S集
	for (i = 1; i < G.vexnum; ++i)
	{
		min = INFINITY;
		for (w = 0; w < G.vexnum; ++w)
		{
			//w顶点在V-S中
			if (!final[w])
			{
				//w顶点离v0顶点更近
				if (D[w].adj < min)
				{
					v = w;
					min = D[w].adj;
				}
			}
		}
		final[v] = TRUE;//离v0顶点最近的v加入S集
		//更新当前最短路径和距离
		for (w = 0; w < G.vexnum; ++w)
		{
			//修改D[w]和P[w]
			if (!final[w] && (min + G.arcs[v][w].adj < D[w].adj))
			{
				D[w].adj = min + G.arcs[v][w].adj;
				P[w] = P[v];
				P[w][w] = TRUE;
			}
		}


	}
	
	for (i = 0; i < G.vexnum; ++i)
	{
		if(i!=v0)
		{
			printf("%3c  %3c  ",G.vexs[v0],G.vexs[i]);
			if (D[i].adj != INFINITY)
				printf("%5d    ", D[i]);
			cout << "(";
			for (j = 0; j < G.vexnum; ++j)
			{
				if (P[i][j])
					cout << G.vexs[j];
			}
			cout << ")";
			cout << endl;
		}
	}
}

void main()
{
	MGraph G;
	int v0;
	PathMatrix P;
	ShortPathTable D;
	CreateDN(G);
	list(G);
	cout << "输入源点序号v0:";
	cin >> v0;
	cout << "输出从源点" << v0 << "到其余顶点的最短路径如下:" << endl;
	cout << "始点 终点 路径长度 最短路径" << endl;
	ShortestPath_DIJ(G, v0, P, D);
	cout << endl;
	system("pause");
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
离字典,将起始节点的距离设为0,其他节点的距离设为无穷大 distances = {node: sys.maxsize for node in graph} distances[start] = 0 # 初始化已访问节点的集合和未访以下是使用问节点D的集ijkstra合 visited = set() unvisited算法求解最短路径的Python = set(graph) while unvisited: # 代码示例: ```python class D选择当前ijkstra距: def __init__(self, graph离最小的节点 , start, current goal): self.graph = graph # 邻接表_node = min(unvisited, key=lambda self node: distances[node]) # 更新.start = start当前节点的 # 起邻居节点点 self.goal =的距离 goal # 终点 for neighbor in graph self.open[current_node]: _list = {} if neighbor in # open 表 self.closed_list unvisited: new_distance = distances[current_node] + = {} graph[current_node][neighbor # closed 表 self.open_list[start] if new_distance] = < distances[neighbor]: 0.0 # 将 distances[neighbor] = new_distance # 将当前起点放入 open_list 中 self.parent = {节点标记start:为已访 None} 问,并从未访问集合中移除 visited.add # 存储节点的父子关系。键为(current_node) 子节点, unvisited值为父.remove(current_node) return节点。方便做最 distances def print后_path(dist路径的ances,回 start溯 self.min, end): _dis = None # 根 # 最短路径的长度 def shortest_path据距离字典和终点节点(self): while True: ,逆向 if self打印路径.open_list is path = [end None: ] print('搜索 current_node =失败 end while current_node !=, 结束!') break distance start: , min_node = for neighbor in graph min(zip[current_node]: if(self.open_list distances[current.values(), self_node] ==.open_list.keys distances[neighbor())) #] + graph 取出距[neighbor][current_node]: 离最小的节点 self path.open_list.pop.append(min_node)(neighbor) current_node = neighbor break path.reverse() # 将其从 open_list 中去除 self print.closed("_list[minShortest_node] = path from", distance # 将节点加入 closed start, "to", end,_list ":", "->".join(path)) # 示例 中 if min_node == self.goal: # 如果节点为的邻接矩阵终点 self.min_dis = distance 表示 graph shortest = { _path = [ 'Aself.goal]': {'B': # 5, 'C 记录从': 终1}, 点回溯的路径 'B

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值