问题:找出如下图中v0 到各点的最短距离,并输出距离及路径
程序运行截图:
分析:
在图中找到V0到各点的最小短距离路径:** 使用dijkstra算法求单源最短路径**
- 用dist[]数组来存储v0到各点的最短距离,path[]来存储路径,path[w]= v即w点经过v,collected[]记录该点是否被收入s
- 第一步:初始化,所有dist设置为无穷大,path设置为-1
- 第二步:进入主循环前,v0的邻接点初始化,path和dist初始化,再将v0并入S集
- 第三步:进入主循环,在未收录的找到v0到其余n-1个顶点最短路径的顶点,并入S,如果找不到这样的点,退出循环
- 第四步:遍历v的每个邻接点,更新当前最短路径及距离
dijkstra函数
void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist)
/*在图中找到V0到各点的最小短距离路径*/
{
int i,v,w;
int min;//最短路径
int collected[MaxSize];//存储顶点是否收录到S
for (v = 0; v < N.vexnum; v++) // 初始化v0到v的距离,
{
if (N.arc[v0][v].adj < INFINITY)//邻接点
{
path[v] = 0;
dist[v] = N.arc[v0][v].adj;
}
else
{
path[v] = -1;
dist[v] = INFINITY;
}
collected[v] = 0;
}
collected[v0] = 1;//先将v0并入s
dist[v0] = 0;
//path[0] = 0;
//开始主循环
while (1)
{
v = 0;
min = INFINITY;
for (w = 0; w < N.vexnum ; w++) //在未收录的顶点中找到距离最小的顶点
{
if(collected[w] == 0)
if (dist[w] < min)
{
v = w;
min = dist[w];
}
}
if (v == 0) //如果这样的v不存在
break;
collected[v] = 1;//将该并入s
for (w = 0; w < N.vexnum ; w++) 在V的邻接点中更新当前最短路径及距离
{
if(N.arc[v][w].adj < INFINITY)
if (collected[w] == 0)
if (dist[v] + N.arc[v][w].adj < dist[w])
{
dist[w] = dist[v] + N.arc[v][w].adj;
path[w] = v;
}
}
}
}
所有代码
#include "pch.h"
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
typedef char VertexType; //相当于VertexType 为char[4]
#define INFINITY 65535 //最大值
#define MaxSize 50 //最大顶点个数
typedef enum{DG,DN,UDG,UDN}GrandKind;//有向图,有向网,无向图,无向网
typedef int VRType; //顶点关系类型,无权图用0或1,有权图,则为权值类型
typedef char InfoPtr;
typedef struct
{
VRType adj;//对于无权图用0或1表示,1表示相邻,0表示不相邻;对于带权值得图存储权值
InfoPtr * info;//该弧相关信息指针,与弧或边的相关信息
} ArcNode, AdjMatrix[MaxSize][MaxSize];
typedef struct //图的类型定义
{
VertexType vex[MaxSize][4];//相当于char[MaxSize][4],用于储存顶点
AdjMatrix arc; // 邻接矩阵,存储边或弧的信息
int vexnum, arcnum;//顶点数和弧的数目
GrandKind kind;//图的定义
}MGraph;
typedef int PathMatrix[MaxSize];//保存最短路径的数组
typedef int ShortPathLength[MaxSize];//定义一个保存从顶点到V的最短距离的数组
void CreateGraph(MGraph *N);
int LocateVertex(MGraph N, VertexType *v);
void DestroyGraph(MGraph *N);
void DisplayGraph(MGraph N);
void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist);//Dijkstra算法
void PrintPath(MGraph N, int v, PathMatrix path)//递归打印路径
{
/*if (v != 0)
{
printf("-%s", N.vex[path[v]]);
PrintPath(N, path[v], path);
}
else
return;*/
while (v!=-1)
{
printf("%s-", N.vex[v]);
v = path[v];
}
}
int main()
{
MGraph N;
ShortPathLength dist;
PathMatrix path;
int i;
printf("创建有向网:\n");
CreateGraph(&N);
DisplayGraph(N);
//DestroyGraph(&N);
Dijkstra(N, 0, path, dist);
printf("顶点%s到各个顶点的最短距离:\n", N.vex[0]);
for (i = 0; i < N.vexnum; i++)
{
printf("%s--%s: dist = %d \n", N.vex[0], N.vex[i], dist[i]);
printf("路径:");
PrintPath(N, i, path);
//printf("%s", N.vex[0]);
printf("\n");
}
return 0;
}
void CreateGraph(MGraph *N)
//
{
int i,j,k,weight;
VertexType v1[4], v2[4];
printf("请输入有向网的顶点数和弧数(以逗号分开):\n");
scanf_s("%d,%d", &(N->vexnum), &(N->arcnum));
printf("请输入%d个顶点的值(<%d个字符)\n", N->vexnum, MaxSize);
for (i = 0; i < N->vexnum; i++)//存储顶点
{
scanf_s("%s", N->vex[i],sizeof(N->vex[0]));
}
for (i = 0; i < N->vexnum; i++)// 初始化邻接矩阵
{
for (j = 0; j < N->vexnum; j++)
{
N->arc[i][j].adj = INFINITY;
N->arc[i][j].info = NULL;
}
}
printf("输入两个顶点和弧的权值(以空格隔开):\n");
for (k = 0; k < N->arcnum; k++)
{
scanf_s("%s %s %d", v1,sizeof(4), v2,sizeof(4) ,&weight);
i = LocateVertex(*N, v1);//找到弧尾顶点的下标
j = LocateVertex(*N, v2);//找到弧顶顶点的下标
N->arc[i][j].adj = weight;
}
N->kind = DN; //类型为有向网
}
int LocateVertex(MGraph N, VertexType *v)
//定位
{
int i;
for (i = 0; i < N.vexnum; i++)
{
if (strcmp(N.vex[i],v)== 0)
return i;
}
return -1;
}
void DestroyGraph(MGraph *N)
//销毁邻接表
{
int i, j;
for (i = 0; i < N->vexnum; i++)
{
for (j = 0; j < N->vexnum; j++)
{
if (N->arc[i][j].info != NULL)
{
free(N->arc[i][j].info);
N->arc[i][j].info = NULL;
}
}
}
N->arcnum = N->vexnum = 0;
}
void DisplayGraph(MGraph N)
//显示邻接表
{
int i, j, k;
printf("输出网的结点和弧:\n");
printf("该网有%d个顶点,%d条弧\n",N.vexnum,N.arcnum);
printf("顶点依次是:");
for (i = 0; i < N.vexnum;i++)
{
printf("%s ", N.vex[i]);
}
printf("网:\n");
printf("i= ");
for (i = 0; i < N.vexnum; i++)
{
printf("%8d", i);
}
printf("\n");
for (i = 0; i < N.vexnum; i++)
{
printf("%8d", i);
for (j = 0; j < N.vexnum; j++)
{
printf("%8d", N.arc[i][j].adj);
}
printf("\n");
}
}
void Dijkstra(MGraph N, int v0, PathMatrix path, ShortPathLength dist)
/*在图中找到V0到各点的最小短距离路径*/
{
int i,v,w;
int min;//最短路径
int collected[MaxSize];//存储顶点是否收录到S
for (v = 0; v < N.vexnum; v++) // 初始化v0到v的距离,
{
if (N.arc[v0][v].adj < INFINITY)//邻接点
{
path[v] = 0;
dist[v] = N.arc[v0][v].adj;
}
else
{
path[v] = -1;
dist[v] = INFINITY;
}
collected[v] = 0;
}
collected[v0] = 1;//先将v0并入s
dist[v0] = 0;
//path[0] = 0;
//开始主循环
while (1)
{
v = 0;
min = INFINITY;
for (w = 0; w < N.vexnum ; w++) //在未收录的顶点中找到距离最小的顶点
{
if(collected[w] == 0)
if (dist[w] < min)
{
v = w;
min = dist[w];
}
}
if (v == 0) //如果这样的v不存在
break;
collected[v] = 1;//将该并入s
for (w = 0; w < N.vexnum ; w++) 在V的邻接点中更新当前最短路径及距离
{
if(N.arc[v][w].adj < INFINITY)
if (collected[w] == 0)
if (dist[v] + N.arc[v][w].adj < dist[w])
{
dist[w] = dist[v] + N.arc[v][w].adj;
path[w] = v;
}
}
}
}