通过迪杰斯特拉算法查找任意可达两点之间的最短路径
这是博主在校学习数据结构时所写的程序,通过展示学校主要地点来使用迪杰斯特拉算法实现求任意可达两点之间的最短距离。使用的是c语言
代码如下:
#define ERROR 0
#define OK 1
#define FALSE 0
#define TRUE 1
#define OVERFLOW -2
#define N 100
#define MAX 300
#define infor 1000
#define INF 10000
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef int Status;
typedef struct ArcCell
{
int adj;
}ArcCell,AdjMatrix[N][N];
typedef struct
{
char vexs[N][MAX];//这样可以输入字符串的顶点;
char ver_infor[N][infor];//用来介绍每个顶点的信息;
AdjMatrix adj_arr;
int vexnum,arcnum;
}MGraph;
typedef int QElemType;
typedef struct QNode
{
struct QNode *next;
QElemType data;
}QNode,*Queueptr;
typedef struct
{
Queueptr front;
Queueptr rear;
}LinkQueue;
typedef struct
{
char *adjvex;
int lowcost;
}Edge;
int visited[N];
Status (*VisitFunc)(int v,MGraph G);
Status CreateUND(MGraph &G);
Status Locatevex(MGraph G,char *s);
Status printf_shortpath(MGraph G);
Status export_data(MGraph &G);
Status search_place(MGraph G);
void shortest_path(MGraph G,int start, int end);
void print_shortest_path(int * distance, int * path, int * used, int start, int end,MGraph G);
void background();
Status FirstAdjVex(MGraph G,int v);
Status NextAdjVex(MGraph G,int v,int w);
void BFSTraverse(MGraph G,Status (*Visit)(int v,MGraph G));
Status QueueEmpty(LinkQueue Q);
Status DeQueue(LinkQueue &Q,QElemType &e);
Status EnQueue(LinkQueue &Q,QElemType e);
Status initQueue(LinkQueue &Q);
Status printfElement(int v,MGraph G);
int Minimunm(Edge closedge[],int n);
Status MinspnTree_Prim(MGraph G);
int main()
{
MGraph G;
int start, end,n;
char v[MAX];
char v1[MAX],v2[MAX];
//CreateUND(G);
export_data(G);
printf("-------------------菜单-------------------\n");
printf("|***1:欣赏校园景点 2:设计最佳路线***|\n");
printf("|***3:查询景点信息 4:校园景点遍历***|\n");
printf("|***5:最小生成树 6:退 出 菜 单***|\n");
printf("------------------------------------------\n");
printf("请选择功能:");
scanf("%d",&n);
while(n!=6)
{
if(n==1)
{
background();
}
if(n==2)
{
printf("请输入起点:");
scanf("%s", &v1);
printf("请输入终点:");
scanf("%s", &v2);
start=Locatevex(G,v1);
end=Locatevex(G,v2);
shortest_path(G,start,end);
}
if(n==3)
{
search_place(G);
}
if(n==4)
{
BFSTraverse(G,printfElement);
}
if(n==5)
{
MinspnTree_Prim(G);
}
printf("请继续操作:");
scanf("%d",&n);
}
return OK;
}
Status CreateUND(MGraph &G)//创建图函数
{
FILE *fp;
int i=0,j,n,m;
char v1[MAX],v2[MAX];
fp=fopen("map.txt","w");
if(!fp)
{
printf("can't open file\n");
exit(0);
}
printf("请输入顶点数:");
scanf("%d",&G.vexnum);
printf("请输入边数:");
scanf("%d",&G.arcnum);
fflush(stdin);
fprintf(fp,"%d",G.vexnum);
fputs("\n",fp);
fprintf(fp,"%d",G.arcnum);
fputs("\n",fp);
while(i<G.vexnum)
{
printf("请输入顶点名称:");
gets(G.vexs[i]);
printf("请输入该顶点的信息:");
gets(G.ver_infor[i]);
fprintf(fp,"%s",G.vexs[i]);
fputs("\n",fp);
fprintf(fp,"%s",G.ver_infor[i]);
fputs("\n",fp);
i++;
}i=0;
while(i<G.vexnum)
{
j=0;
while(j<G.vexnum)
{
if(i==j)
{
G.adj_arr[i][j].adj=0;
}
else
G.adj_arr[i][j].adj=INF;
j++;
}
i++;
}
i=1;
while(i<=G.arcnum)
{
printf("请输入边的第一个顶点:");
gets(v1);
n=Locatevex(G,v1);
printf("请输入边的第二个顶点:");
gets(v2);
fflush(stdin);
m=Locatevex(G,v2);
printf("请输入这条边的权值:");
scanf("%d",&G.adj_arr[n][m].adj);
fflush(stdin);
G.adj_arr[m][n].adj=G.adj_arr[n][m].adj;// 无向图
i++;
}
i=0;
while(i<G.vexnum)
{
j=0;
while(j<G.vexnum)
{
fprintf(fp,"%d",G.adj_arr[i][j].adj);
fputs("\n",fp);
j++;
}
i++;
}
fclose(fp);
return OK;
}
Status Locatevex(MGraph G,char v[])//取下标函数
{
int i=0;
while(i<G.vexnum)
{
if(strcmp(G.vexs[i],v)==0)
return i;
i++;
}
if(i>=G.vexnum)
{
return -1;
}
}
Status export_data(MGraph &G)//将文件中的数据导出;
{
FILE *fp;
int i=0,j,n,m;
fp=fopen("map.txt","r");
if(!fp)
{
printf("can't open file\n");
exit(0);
}
fscanf(fp,"%d%d",&G.vexnum,&G.arcnum);
//printf("测试%d,%d",G.vexnum,G.arcnum);
while(i<G.vexnum)
{
fscanf(fp,"%s",&G.vexs[i]);
//printf("测试%s\n",G.vexs[i]);
fscanf(fp,"%s",&G.ver_infor[i]);
//printf("测试%s\n",G.ver_infor[i]);
i++;
}
i=0;j=0;
while(i<G.vexnum)
{
j=0;
while(j<G.vexnum)
{
fscanf(fp,"%d",&G.adj_arr[i][j].adj);
//printf("测试%d\n",G.adj_arr[i][j].adj);
j++;
}
i++;
}
fclose(fp);
return OK;
}
void shortest_path(MGraph G,int start, int end)// 基于迪杰斯特拉算法的最短路径函数
{
int distance[G.vexnum]; // 用于存放起始点到其余各点的最短距离
int path[G.vexnum]; // 用于存放起始点到其余各点最短路径的前一个顶点
int used[28]={0}; // 用于标记该顶点是否已经找到最短路径
int i, j, min_node, min_dis, pass_flag=0;
for(i=0;i<G.vexnum;i++)
{
distance[i]=G.adj_arr[start][i].adj; //初始化距离数组
if(G.adj_arr[start][i].adj<INF)
path[i]=start; // 初始化路径数组
else
path[i]=-1;
}
used[start]=1;
path[start]=start;
for(i=0;i<G.vexnum;i++)
{
min_dis=INF;
for(j=0;j<G.vexnum;j++)
{
if(used[j]==0&&distance[j]<min_dis)
{
min_node=j;
min_dis=distance[j];
pass_flag=1; // 标记是否存在通路
}
}
if(pass_flag!=0)
{
used[min_node]=1;
for(j=0;j<G.vexnum;j++)
{
if(used[j]==0)
{
if(G.adj_arr[min_node][j].adj<INF&&distance[min_node]+G.adj_arr[min_node][j].adj<distance[j])
{
distance[j]=distance[min_node]+G.adj_arr[min_node][j].adj;
path[j]=min_node;
}
}
}
}
else
printf("没有路径可以到达!\n");
}
print_shortest_path(distance,path,used,start,end,G);
}
void print_shortest_path(int * distance, int * path, int * used, int start, int end,MGraph G)// 输出最短路长并打印最短路径
{
int i = 0, pre, inverse_path[G.vexnum];
printf("The shortest length from %s to %s is: %d\n", G.vexs[start],G.vexs[end], distance[end]);
inverse_path[i] = end;
pre = path[end];
if(pre == -1)
printf("There is no path!\n");
else
{
while(pre != start)
{
inverse_path[++i] = pre;
pre = path[pre];
}
inverse_path[++i] = start;
printf("The shortest path from %s to %s is:\n", G.vexs[start],G.vexs[end]);
for(; i > 0; i--)
{
printf("%s -> ", G.vexs[inverse_path[i]]);
}
printf("%s\n", G.vexs[inverse_path[i]]);
}
}
Status search_place(MGraph G)//查找功能;
{
int i=0,n;
printf("校园场所具体信息查询!\n");
while(i<G.vexnum)
{
printf("%s:%d ",G.vexs[i],i);
i++;
}
printf("\n");
printf("请输入选项:");
scanf("%d",&n);
printf("场所%s:%s\n",G.vexs[n],G.ver_infor[n]);
}
//广度优先遍历;
Status initQueue(LinkQueue &Q)//创建一个空队链函数
{
Q.front=Q.rear=(Queueptr)malloc(sizeof(QNode));
if(!Q.front)exit(OVERFLOW);
Q.front->next=NULL;
return OK;
}
Status EnQueue(LinkQueue &Q,QElemType e) //入队函数
{
Queueptr p;
p=(Queueptr)malloc(sizeof(QNode));
if(!p)exit(OVERFLOW);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
Status DeQueue(LinkQueue &Q,QElemType &e)//出队函数
{
Queueptr p;
if(Q.rear==Q.front)
{
return ERROR;
}
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(p==Q.rear)
Q.rear=Q.front;
free(p);
return OK;
}
Status QueueEmpty(LinkQueue Q) //判断栈空函数
{
if(Q.rear==Q.front)
{
return OK;
}
else
return FALSE;
}
Status printfElement(int v,MGraph G)
{
printf("%s ",G.vexs[v]);
return OK;
}
void BFSTraverse(MGraph G,Status (*Visit)(int v,MGraph G)) //广度优先遍历
{
LinkQueue Q;
int v,w,u;
for(v=0;v<G.vexnum;++v)
visited[v]=FALSE;
initQueue(Q);
for(v=0;v<G.vexnum;++v)
{
if(!visited[v])
{
visited[v]=TRUE;
Visit(v,G);
EnQueue(Q,v);
while(!QueueEmpty(Q))
{
DeQueue(Q,u);
for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w))
{
if(!visited[w])
{
visited[w]=TRUE;
Visit(w,G);
EnQueue(Q,w);
}
}
}
}
}
printf("\n");
}
Status FirstAdjVex(MGraph G,int v)
{
int i=0,w,j=0;
i=v;
if(i==-1)
{
printf("该顶点不存在\n");
return ERROR;
}
else
{
while(j<G.vexnum)
{
if(G.adj_arr[i][j].adj!=INF&&G.adj_arr[i][j].adj!=0)
{
return j;
}
j++;
}
if(j=G.vexnum)
{
return -1;
}
}
}
Status NextAdjVex(MGraph G,int v,int w)
{
int i=0,j=0;
i=v;
j=w;
if(i==-1)
{
printf("顶点V不存在\n");
return ERROR;
}
else
{
j=j+1;
while(j<G.vexnum)
{
if(G.adj_arr[i][j].adj!=INF&&G.adj_arr[i][j].adj!=0)
{
return j;
}
j++;
}
if(j=G.vexnum)
{
return -1;
}
}
}
//普利姆算法构造一个最小生成树;
Status MinspnTree_Prim(MGraph G)
{
int i,j,k,n;
char v[MAX];
Edge closedge[N];
printf("请任意输入一个顶点");
scanf("%s",v);
fflush(stdin);k=Locatevex(G,v);
for(j=0;j<G.vexnum;j++) //辅助数组初始化;
{ closedge[j].adjvex=(char *)malloc(MAX*sizeof(char));
strcpy(closedge[j].adjvex,v);
closedge[j].lowcost=G.adj_arr[k][j].adj;
}
for(i=0;i<G.vexnum;i++)
{ printf("%s---%s ",closedge[k].adjvex,G.vexs[k]);
k=Minimunm(closedge,G.vexnum);
closedge[k].lowcost=0; //把下标为k的顶点纳入;
for(j=0;j<G.vexnum;j++) //重新排序;
{
if(closedge[j].lowcost!=0&&G.adj_arr[k][j].adj<closedge[j].lowcost)
{
closedge[j].adjvex=(char *)malloc(MAX*sizeof(char));
strcpy(closedge[j].adjvex,G.vexs[k]);
closedge[j].lowcost=G.adj_arr[k][j].adj;
}
}
}
}
int Minimunm(Edge closedge[],int n)
{
int i,j;
int min=INF;
for(i=0,j=0;i<n;i++)
{
if(closedge[i].lowcost)
{
if(closedge[i].lowcost<=min)
{
min=closedge[i].lowcost;
j=i;
}
}
}
return j;
}
void background()
{
printf("***********************************************校园景点***********************************************\n");//校园图纸;
printf("|--------------------------------------------------------东门-------------------|---------------------\n");
printf("| | | \n");
printf("| | | \n");
printf("| 27 | \n");
printf("| | | \n");
printf("| 医院------------25-------------老女寝-----16----行政楼 | \n");
printf("| | | | | \n");
printf("| | 8 6 | \n");
printf("| | | | | \n");
printf("| |--------------22--------------1食堂----11-----外语楼 | \n");
printf("| | | | | \n");
printf("| 34 17 11 | \n");
printf("| | | | | \n");
printf("| | 操场-----15-----逸夫楼------12-----学校正大门 \n");
printf("| | | | \n");
printf("| | | 18 \n");
printf("| 网球场 | | \n");
printf("| | 24-----------------18----------------南门-----2---小吃街 \n");
printf("| | | | \n");
printf("| 18 | 11 \n");
printf("| | | | \n");
printf("| 女寝-----9-----图书馆-----7----音乐广场-----8----明德楼-------4------机电楼 \n");
printf("| | | | | \n");
printf("北门--10--16 14 17 | \n");
printf("| | | | | \n");
printf("| D楼-------10------B楼------11------A楼----8---C楼----6---综合楼 | \n");
printf("| | | | | \n");
printf("| 12 | 8 | \n");
printf("| | 15 | | \n");
printf("| 2.3食堂 |------------------14-----------------工创中心 | \n");
printf("| | | | \n");
printf("| 6 -------8------男寝----------4-------新女寝 | \n");
printf("| | | \n");
printf("| 菜鸟驿站 | \n");
printf("|-------------------------------------------------------------------------------|---------------------\n");
printf("***********************************************校园景点***********************************************\n");
}