用Dijkstra算法求有向图最短路径

要求
1、根据输入构造一个有向网络;
2、输出该有向网络对应的矩阵;
3、求出该有向网络的最短路径。
代码

#include<stdio.h>
#define INFINITY 100000		//最大值   ∞
#define MVNum 100                       					//最大顶点数            						
int D[MVNum];	                    				//用于记录最短路的长度
bool S[MVNum];          							//标记顶点是否进入S集合
int Path[MVNum];									//用于记录最短路顶点的前驱
typedef struct {
	char vexs[MVNum];            						//顶点表 
	int arcs[MVNum][MVNum];      						//邻接矩阵 
	int vexnum, arcnum;                					//图的当前点数和边数 
}AMGraph;
int LocateVex(AMGraph G, char v) {
	//确定点v在G中的位置
	for (int i = 0; i < G.vexnum; ++i)
		if (G.vexs[i] == v)
			return i;
}//LocateVex
void CreateUDN(AMGraph& G) {
	//采用邻接矩阵表示法,创建无向网G 
	 //采用邻接矩阵表示法,创建无向网G 
	int i, j, k;
	printf("请输入总顶点数,总边数,以空格隔开:\n");
	scanf_s("%d  %d", &G.vexnum, &G.arcnum);//输入总顶点数,总边数
	getchar();
	printf("依次输入点的名称,如A\n");
	for (i = 0; i < G.vexnum; i++)
	{
		scanf_s("%c", &G.vexs[i]);       //依次输入点的信息 
	}
	for (i = 0; i < G.vexnum; i++)        //初始化邻接矩阵,边的权值均置为极大值INFINITY 
	{
		for (j = 0; j < G.vexnum; j++)
		{
			G.arcs[i][j] = INFINITY;
		}
	}
	printf("请依次输入边依附的顶点及权值,如AB 5\n");
	for (k = 0; k < G.arcnum; k++)//构造邻接矩阵 
	{							
		char v1, v2;
		char ch;
		int w;
		getchar();
		v1 = getchar();
		v2 = getchar();
		getchar();
		getchar();
		scanf_s("%d", &w);//输入一条边依附的顶点及权值
		i = LocateVex(G, v1);  j = LocateVex(G, v2);		//确定v1和v2在G中的位置,即顶点数组的下标 
		G.arcs[i][j] = w;									//边<v1, v2>的权值为w 
	}//for
}//CreateUDN
void PrintUDN(AMGraph G)//输出邻接矩阵
{
	int i, j;
	printf("         ");
	for (i = 0; i < G.vexnum; i++)
	{
		printf("%c\t ", G.vexs[i]);
	}
	printf("\n");
	for (i = 0; i < G.vexnum; ++i)
	{
		printf("%c\t ", G.vexs[i]);
		for (j = 0; j < G.vexnum; ++j)
		{
			if (i == j)
			{
				printf("0\t ");
			}
			else if (G.arcs[i][j] == INFINITY)
			{
				printf("∞\t ");
			}
			else
			{
				printf("%d\t ", G.arcs[i][j]);
			}
		}
		printf("\n");
	}
}
void ShortestPath_DIJ(AMGraph G, int v0) //用Dijkstra算法求有向网G的v0顶点到其余顶点的最短路径 
{
	int v, i, w, min;                //n为G中顶点的个数 
	for (v = 0; v <G.vexnum; ++v) 
	{             					  //n个顶点依次初始化 
		S[v] = false;                //S初始为空集 
		D[v] = G.arcs[v0][v];           			         //将v0到各个终点的最短路径长度初始化为弧上的权值 
		if (D[v] < INFINITY&&D[v]!=0)   
		{
            Path[v] = v0; 
		}                                                    //如果v0和v之间有弧,则将v的前驱置为v0 
		else
		{
            Path[v] = -1;                                    //如果v0和v之间无弧,则将v的前驱置为-1 
		}
			               					
	}
	S[v0] = true;                    							//将v0加入S 
	D[v0] = 0;                      							//源点到源点的距离为0 
	/*每次求得v0到某个顶点v的最短路径,将v加到S集―*/
	for (i = 1; i < G.vexnum; i++)//对其余n-1个顶点,依次进行计算 
	{									
		min = INFINITY;
		for (w = 0; w < G.vexnum; w++)
			if (!S[w] && D[w]!=0&&D[w] < min) //选择一条当前的最短路径,终点为v 
			{						
				v = w;
				min = D[w];
			}//if         	
		S[v] = true;                   						//将v加入S 
		for (w = 0; w < G.vexnum; w++)           		    //更新从v0出发到集合V?S上所有顶点的最短路径长度 
			if (!S[w] && (D[v] + G.arcs[v][w] < D[w])) 
			{
				D[w] = D[v] + G.arcs[v][w];   				//更新D[w] 
				Path[w] = v;              					//更改w的前驱为v 
			} 
	}
}
void DisplayPath(AMGraph G, int begin, int temp) //显示最短路
{
	if (Path[temp] !=-1 ) 
	{
		DisplayPath(G, begin, Path[temp]);
		printf("%c-->", G.vexs[Path[temp]]);
	}
}//DisplayPath
void main()
{
	AMGraph G;
	int i, j;
	CreateUDN(G);
	PrintUDN(G);
	ShortestPath_DIJ(G, 0);
	printf("最短路径为:\n");
	for (i = 1; i < G.vexnum; i++)
	{
		DisplayPath(G,0,i);
		if (D[i] < INFINITY)
		{
			printf("%c ", G.vexs[i]);
			printf("长度%d\n", D[i]);
		}
		else
		{
			printf("%c-->%c ", G.vexs[0], G.vexs[i]);
			printf("无路径\n");
		}
	}
}
**输入示例**
6  8
ABCDEF
AC  10
AE  30
AF  100
BC  5
CD  50
DF  10
ED  20
EF  60
**输出**
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201213223015553.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzUxMjI0NDky,size_16,color_FFFFFF,t_70)

猜你喜欢

转载自blog.csdn.net/qq_51224492/article/details/111146944