数据结构之有向网邻接矩阵Dijkstra实现源点至其余各顶点最短路径

本文详细介绍了如何利用Dijkstra算法,在有向图的邻接矩阵表示中求解从源点到所有其他顶点的最短路径问题。通过对图的遍历和路径权重更新,确保找到最短路径。该方法适用于解决图论中的路径寻找问题。
摘要由CSDN通过智能技术生成

#include<iostream>
using namespace std;
#define MAXVEX 100
#define INFINITY 65535
typedef char VNode;
typedef int ANode;
typedef struct MGraph
{
	VNode Vex[MAXVEX];
	ANode Arc[MAXVEX][MAXVEX];
	int Vnums;
	int Anums;
}MGraph;

void CreateNGraph(MGraph &G)
{
	int i, j, k;
	ANode w;
	cin >> G.Vnums >> G.Anums;
	for (i = 0; i < G.Vnums; ++i)
		cin >> G.Vex[i];
	for (i = 0; i < G.Vnums; ++i)
		for (j = 0; j < G.Vnums; ++j)
			G.Arc[i][j] = INFINITY;
	for (k = 0; k < G.Anums; ++k)
	{
		cin >> i >> j >> w;
		if (i != j)
		{
			G.Arc[i][j] = w;
			G.Arc[j][i] = G.Arc[i][j];
		}
	}
}

int LocateVex(MGraph G, VNode v)
{
	int i;
	for (i = 0; i<G.Vnums; ++i)
		if (G.Vex[i] == v)
			return i;
	return -1;
}

VNode GetVex(MGraph G, int i)
{
	if (i >= G.Vnums || i < 0)
		exit(-1);
	return G.Vex[i];
}

bool PutVex(MGraph &G, VNode v, VNode value)
{
	int i;
	i = LocateVex(G, v);
	if (i < 0)
		return false;
	G.Vex[i] = value;
	return true;
}

int FirstAdjvexN(MGraph G, VNode v)
{
	int i, k;
	k = LocateVex(G, v);
	for (i = 0; i < G.Vnums; ++i)
		if (G.Arc[k][i] != INFINITY)
			return i;
	return -1;
}

int NextAdjvexN(MGraph G, VNode v, VNode w)
{
	int i, k1, k2;
	k1 = LocateVex(G, v);
	k2 = LocateVex(G, w);
	for (i = k2 + 1; i < G.Vnums; ++i)
		if (G.Arc[k1][i] != INFINITY)
			return i;
	return -1;
}

void InsertVexN(MGraph &G, VNode v)
{
	int i;
	for (i = 0; i <= G.Vnums; ++i)
	{
		G.Arc[i][G.Vnums] = INFINITY;
		G.Arc[G.Vnums][i] = INFINITY;
	}
	G.Vnums++;
}

bool VisitTag[MAXVEX];

void Visit(VNode v)
{
	cout << v << " ";
}

void DFS(MGraph G, int i)
{
	int j;
	Visit(G.Vex[i]);
	VisitTag[i] = true;
	for (j = FirstAdjvexN(G, G.Vex[i]); j >= 0; j = NextAdjvexN(G, G.Vex[i], G.Vex[j]))
		if (!VisitTag[j])
			DFS(G, j);
}

void DFST(MGraph G)
{
	int i;
	for (i = 0; i < G.Vnums; ++i)
		VisitTag[i] = false;
	for (i = 0; i < G.Vnums; ++i)
		if (!VisitTag[i])
			DFS(G, i);
	cout << endl;
}

/******************************************************/
#define QSIZE MAXVEX
typedef struct Queue
{
	int *pBase;
	int Front;
	int Rear;
}Queue;

void InitQueue(Queue &Q)
{
	Q.pBase = new int[QSIZE];
	Q.Front = 0;
	Q.Rear = 0;
}

bool QueueFull(Queue Q)
{
	if ((Q.Rear + 1) % QSIZE == Q.Front)
		return true;
	else
		return false;
}

bool QueueEmpty(Queue Q)
{
	if (Q.Rear == Q.Front)
		return true;
	else
		return false;
}

void EnQueue(Queue &Q, int i)
{
	if (QueueFull(Q))
		return;
	Q.pBase[Q.Rear] = i;
	Q.Rear = (Q.Rear + 1) % QSIZE;
}

void DeQueue(Queue &Q, int &i)
{
	if (QueueEmpty(Q))
		return;
	i = Q.pBase[Q.Front];
	Q.Front = (Q.Front + 1) % QSIZE;
}

void BFST(MGraph G)
{
	int i, j;
	Queue Q;
	InitQueue(Q);
	for (i = 0; i < G.Vnums; ++i)
		VisitTag[i] = false;
	for (i = 0; i < G.Vnums; ++i)
	{
		if (!VisitTag[i])
		{
			Visit(G.Vex[i]);
			VisitTag[i] = true;
			EnQueue(Q, i);
			while (!QueueEmpty(Q))
			{
				DeQueue(Q, i);
				for (j = FirstAdjvexN(G, G.Vex[i]); j >= 0; j = NextAdjvexN(G, G.Vex[i], G.Vex[j]))
				{
					if (!VisitTag[j])
					{
						Visit(G.Vex[j]);
						VisitTag[j] = true;
						EnQueue(Q, j);
					}
				}

			}
		}
	}
	cout << endl;
}

/*******************************************************/

typedef int PathArc[MAXVEX];//存储最短路径下标
typedef int ShortPathTable[MAXVEX];//存储出发点到各点路径的权值和

void ShortestPath_Dijkstra(MGraph G, int m, PathArc P, ShortPathTable D)
{
	int i, j, k, min;
	bool final[MAXVEX];//etc:final[i]==true,表示求得了m至i的最短路径
	for (i = 0; i < G.Vnums; ++i)
	{
		final[i] = false;
		D[i] = G.Arc[m][i];
		P[i] = 0;
	}
	D[m] = 0;
	P[m] = -1;//显然没有至原始出发点的路径,故下标设-1
	final[m] = true;//原始出发点
	for (i = 1; i < G.Vnums; ++i)
	{//循环一次求得原始出发点至某一顶点的最短路径
		min = INFINITY;//暂时设置,以淘汰对应非邻接点
		for (j = 0; j < G.Vnums; ++j)
		{
			if (!final[j] && D[j]<min)
			{
				k = i;
				min = D[j];
			}
		}//寻得距离当前顶点更近的顶点
		final[k] = true;//求得出发点至k位置顶点的最短路径并标记之
		for (j = 0; j < G.Vnums;++j)
		{
			if (!final[j] && (min + G.Arc[k][j]) < D[j])
			{//寻找到了更短的路径
				D[j] = min + G.Arc[k][j];//更新出发点至j点的当前路径长度和
				P[j] = k;//值更新为k
			}
		}
	}
}

void PrintShortestPathDIJ(MGraph G,int m)
{
	PathArc P;
	ShortPathTable D;
	int i, j;
	ShortestPath_Dijkstra(G,m, P, D);
	for (i = G.Vnums-1; i >= 0; i--)
	{
		j = i;
		while (P[j] != -1 && P[j] != 0)
		{
			cout << "v" << j << "<-" << "v" << P[j] << "  ";
			j = P[j];
		}
		cout << "v" << j << "<-" << "v" << m << "  ";
		cout << endl;
	}
	cout << endl;
}

int main(void)
{
	MGraph G;	
	CreateNGraph(G);
	PrintShortestPathDIJ(G, 2);
	DFST(G);
	BFST(G);
	return(0);
}

以下是使用C++实现Dijkstra算法求解源点到其余顶点最短路径长度的代码: ```c++ #include <iostream> #include <cstring> using namespace std; const int MAXN = 205; const int INF = 0x3f3f3f3f; int graph[MAXN][MAXN]; // 邻接矩阵存储图 int dis[MAXN]; // dis[i]表示源点到节点i的最短路径长度 bool vis[MAXN]; // vis[i]表示节点i是否已被加入最短路径树 int n, m; // n为节点数,m为边数 void dijkstra(int s) { memset(dis, INF, sizeof(dis)); memset(vis, false, sizeof(vis)); dis[s] = 0; for (int i = 1; i <= n; i++) { int u = -1; for (int j = 1; j <= n; j++) { if (!vis[j] && (u == -1 || dis[j] < dis[u])) { u = j; } } vis[u] = true; for (int v = 1; v <= n; v++) { if (!vis[v] && graph[u][v] != INF) { if (dis[u] + graph[u][v] < dis[v]) { dis[v] = dis[u] + graph[u][v]; } } } } } int main() { cin >> n >> m; memset(graph, INF, sizeof(graph)); for (int i = 1; i <= n; i++) { graph[i][i] = 0; // 自身到自身距离为0 } for (int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; graph[u][v] = min(graph[u][v], w); // 若存在重边,取边权最小值 } int s; cin >> s; // 源点编号 dijkstra(s); for (int i = 1; i <= n; i++) { if (dis[i] == INF) { cout << s << "到" << i << "无路径" << endl; } else { cout << s << "到" << i << "的最短路径长度为:" << dis[i] << endl; } } return 0; } ``` 输入格式为节点数n和边数m,接下来m行每行三个整数u、v、w,表示有一条从u到v的边,边权为w。程序会输出源点到每个节点的最短路径长度,若源点到某节点不存在路径则输出“源点到该节点无路径”。 具体实现是使用贪心策略,每次从未加入最短路径树的节点中找到距离源点最近的节点u,将u加入最短路径树,并更新源点到其它节点的最短路径长度。时间复杂度为O(n^2)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值