#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
/*--------------------------------- 有向图 <邻接矩阵> 存储表示 --------------------------*/
#define INFINITY 255
#define MAX_VERTEX_NUM 50
typedef char VertexType;
typedef struct ArcCell
{
int distance;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct
{
VertexType CityName[MAX_VERTEX_NUM][20];
AdjMatrix arcs;
int vexnum,arcnum;
}MGraph;
/*-------------------------------------- 函数菜单操作 ------------------------------*/
void ReturnMenu()
{
printf("\n\t****************************************************************\n");
printf ("\t* 返回 (Y) 退出 (E) * \n");
printf("\t****************************************************************\n\n\n");
}
/*--------------------------------- 有向图 <邻接矩阵> 函数操作 --------------------------*/
Status LocateVex(MGraph G,VertexType u[20])
{ /* 初始条件:图 G 存在,u 和 G 中顶点有相同特征 */
/* 操作结果:若 G 中存在顶点 u, 则返回该顶点在图中位置;否则返回 - 1 */
int i;
for(i=0;i<G.vexnum;++i)
if(strcmp(u,G.CityName[i])==0)
return i;
return -1;
}
Status CreatDN(MGraph &G)
{
int i,j,k,w;
VertexType v1[20],v2[20];
printf ("请输入总城市数:\t");
scanf("%d",&G.vexnum);
printf ("请输入各城市间路径数:\t");
scanf("%d",&G.arcnum);
fflush(stdin);
printf ("\n\n------------------------ 下面请输入各城市名称 ------------------------\n\n");
for(i = 0;i < G.vexnum;i++)
{
printf ("第 % d 个城市名为:\t",i+1);
gets(G.CityName[i]);
}
for(i = 0;i < G.vexnum;i++)
for(j = 0;j < G.arcnum; j++)
{
G.arcs[i][j].distance = INFINITY;
}
printf ("\n\n------------------------ 下面请输入各城市间的距离 --------------------\n\n");
for(k = 0;k < G.arcnum;k++)
{
printf ("\n 请输入第 % d 条路径信息:\n",k+1);
printf ("请输入 A 城市名:\t");
gets(v1);
printf ("请输入 B 城市名:\t");
gets(v2);
printf ("请输入 A 城市和 B 城市间的距离:\t");
scanf("%d",&w);
fflush(stdin);
printf("\n");
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j].distance = w;
}
return OK;
}
void ShortestPath_DIJ(MGraph G,int v0,int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM],int D[MAX_VERTEX_NUM])
{
// 用 Dijkstra 算法求有向网 G 的 v0 顶点到其余顶点 v 的最短路径 P [v]
// 及其带权长度 D [v]。
// 若 P [v][w] 为 TRUE,则 w 是从 v0 到 v 当前求得最短路径上的顶点。
//final [v] 为 TRUE 当且仅当 v∈S, 即已经求得从 v0 到 v 的最短路径。
int i=0,j, v,w,min;
bool final[MAX_VERTEX_NUM];
for (v=0; v<G.vexnum; ++v)
{
final[v] = FALSE;
D[v] = G.arcs[v0][v].distance;
for (w=0; w<G.vexnum; ++w)
P [v][w] = FALSE; // 设空路径
if (D[v] < INFINITY)
{
P[v][v0] = TRUE;
P[v][v] = TRUE;
}
}
D[v0] = 0;
final [v0] = TRUE; // 初始化,v0 顶点属于 S 集
//--- 开始主循环,每次求得 v0 到某个 v 顶点的最短路径,并加 v 到 S 集 ---
for (i=1; i<G.vexnum; ++i)
{ // 其余 G.vexnum-1 个顶点
min = INFINITY; // 当前所知离 v0 顶点的最近距离
for (w=0; w<G.vexnum; ++w)
if (!final [w]) //w 顶点在 V-S 中
if (D[w]<min)
{
v = w;
min = D[w];
} //w 顶点离 v0 顶点更近
final [v] = TRUE; // 离 v0 顶点最近的 v 加入 S 集
for (w=0; w<G.vexnum; ++w) // 更新当前最短路径及距离
if (!final[w] && (min+G.arcs[v][w].distance<D[w]))
{ // 修改 D [w] 和 P [w], w∈V-S
D[w] = min + G.arcs[v][w].distance;
for(j=0;j<G.vexnum;j++)
P [w][j] = P [v][j]; // 第 v 行赋值于第 w 行
P[w][w] = TRUE; // P[w] = P[v]+[w]
}
}
}
void showCityName(MGraph G)
{
int i;
char *ch;
printf("\n\t****************************************************************\n");
printf ("\t* 城市名称显示 *\n");
printf("\t****************************************************************\n");
for(i = 0;i<G.vexnum;i++)
{
ch = G.CityName[i];
printf("\t* \t\t %d.",i+1);
while(*ch != '\0')
{
printf("%c",*ch);
ch++;
//puts(G.CityName[j]);
}
printf(" *\n");
}
printf("\t****************************************************************\n");
}
void mainprocess()
{
MGraph G;
int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM], D[MAX_VERTEX_NUM],flags = 0;
int StartPoint,EndPoint,j,check,length,startcheck;
char placeStart[20],placeEnd[20],*ch,p;
CreatDN(G);
/* // 测试数据所用
for( i = 0;i < G.vexnum;i++)
{
for( j = 0; j < G.vexnum;j++)
if(255 == G.arcs[i][j].distance)
printf(" 0");
else
printf("%4d",G.arcs[i][j].distance);
printf("\n");
}*/
do
{
system("cls");
showCityName(G);
LOOP1:
fflush(stdin);
printf ("请输入起点名称:\t");
gets(placeStart);
StartPoint = LocateVex(G,placeStart);
//printf ("起点下标 =% d",StartPoint);
if(-1 == StartPoint)
{
printf ("\n\t\t 警告:无此起点名称!!\n");
goto LOOP1;
}
ShortestPath_DIJ(G,StartPoint,P,D);
LOOP2:
fflush(stdin);
printf ("\n 请输入终点名称:\t");
gets(placeEnd);
EndPoint = LocateVex(G,placeEnd);
//printf ("终点下标 =% d",EndPoint);
if(-1 == EndPoint)
{
printf ("\n\t\t 警告:无此终点名称!!\n");
goto LOOP2;
}
flags = 0;
printf("\n");
printf ("\n\n----------------------------- 结果 ----------------------------\n\n");
startcheck = 0;
printf ("最短路线为:\t");
for(j = StartPoint;j < G.vexnum;j++)
{
check = P[EndPoint][j];
ch = G.CityName[j];
if(1 == check)
{
if(0 == flags)
printf ("开始 -->");
flags++;
while(*ch != '\0')
{
printf("%c",*ch);
ch++;
//puts(G.CityName[j]);
}
printf("-->");
}
else if(0 != check)
break;
}
if(0 != flags )
{
for(j = 0;j < StartPoint;j++)
{
check = P[EndPoint][j];
ch = G.CityName[j];
if(1 == check)
{
flags++;
while(*ch != '\0')
{
printf("%c",*ch);
ch++;
//puts(G.CityName[j]);
}
printf("-->");
}
}
printf ("结束 \n");
}
if(0 == flags)
printf ("\n\t\t 警告:无此路径!\n");
/* // 测试数据所用
for( int i = 0;i < G.vexnum; i++)
{
for( j = 0;j < G.vexnum;j++)
printf("%4d",P[i][j]);
printf("\n");
}
*/
printf("\n");
length = D[EndPoint];
if(length > 0)
{
printf ("最短路长为:\t");
printf("%d\n",length);
}
/* // 测试数据所用
for( i = 0;i < G.vexnum; i++)
{
printf("%4d",D[i]);
}
*/
printf("\n\n");
ReturnMenu();
LOOP3:
printf ("请选择:\t");
p = getchar();
fflush(stdin);
if(p != 'Y' && p != 'y' && p != 'E' && p != 'e')
{
printf ("\n\t\t 警告:功能选择错误!!\n");
goto LOOP3;
}
system("cls");
}while(p == 'Y' || p == 'y');
if(p == 'e' || p == 'E')
exit(0);
}
/*-------------------------------------- 主函数 ---------------------------------------*/
void main()
{
mainprocess();
}
最短路径算法
最新推荐文章于 2024-08-29 16:57:08 发布