掌握图的结构特点及应用,运用所学知识解决现实问题。给出校园各主要建筑的名称信息及有线路联通的建筑之间的距离,利用校园导航系统计算出输入的起点到终点之间的最近距离及线路。
①输入各建筑信息及线路信息,构建图。本项目数据结构为有向网,采用邻接矩阵为存储结构。
②计算给定起点到终点之间最近距离的进行线路。参照迪杰斯特拉算法计算给定两点之间的最短路径。
③根据输入起点和终点,输出线路及总距离。
1.上谷歌获得学校的(截了三张图,拼成一张)地图取主要几个建筑编号构成无向图,用尺子量出权值.
2.有向网的构建 [弧尾,弧头,权值] db文件存储
1,2,1 1,6,12 1,10,6 2,1,1 2,13,3 3,4,2 3,5,2 3,13,2 4,3,2 4,5,2 4,6,12 4,14,5 5,3,2 5,4,2 5,11,3 6,1,12 6,4,12 6,7,4 7,6,4 7,8,2 7,14,13 8,7,2 8,9,3 8,12,4 9,8,3 9,12,3 9,14,13 10,1,6 11,5,3 11,13,3 12,8,4 12,9,3 13,2,3 13,3,2 13,11,3 14,4,5 14,7,13 14,9,13
3.头文件route.h
因为是测试没有对异常情况进行检测.
1 // 2 // Created by Shuai on 2016/1/2. 3 // 4 5 #ifndef UNTITLED_ROUTE_H 6 #define UNTITLED_ROUTE_H 7 8 #define INFINITY SHRT_MAX /* 无穷大 32767,权值无穷大表示不邻接 */ 9 #define N 14 /* 建筑个数 */ 10 #define MAX_PLACE 20 /* 最大建筑个数 */ 11 #define OK 0 12 #define ERROE -1 13 #define OVERFLOW -2 14 #define FALSE 0 15 #define TRUE 1 16 17 18 typedef int PathMatrix[MAX_PLACE][MAX_PLACE]; /* 路径矩阵,二维数组 */ 19 typedef int ShortPathTable[MAX_PLACE]; /* 最短距离表,一维数组 */ 20 21 typedef struct Place{ /* 邻接矩阵元素 */ 22 int adj; /* 权值 */ 23 }Place, PlaceMatrix[MAX_PLACE][MAX_PLACE]; 24 25 typedef struct { /* 有向网 */ 26 int id[MAX_PLACE]; /* 建筑id */ 27 PlaceMatrix places; /* 邻接矩阵 */ 28 int vexnum, arcnum; /* 当前边数.弧数 */ 29 }DiNetwork, *pDiNetwork; 30 31 char name[][20]={"A楼","B楼","C楼","D楼","E楼", 32 "尔雅","耘慧","静远","行政", 33 "北门","东门","南门", 34 "体育场(北)","体育场(南)" 35 }; 36 /* 37 *全局变量 38 */ 39 int route[N]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; /* 记录已经访问的顶点 */ 40 int flag=0; /* 递归试探下标 */ 41 int path[N]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; /* 记录最短路径 */ 42 int min = INFINITY; /* 最小距离,默认无穷大 */ 43 44 #endif //UNTITLED_ROUTE_H
4. 2.cpp
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include "route.h" void printMenu() { puts(" * * * * * * * * * * * * * * * * * * * * * * * * * * * "); puts("% 校园导航系统 %"); puts("% %"); puts("% 1.A楼 6.尔雅 10.北门 13.体育场(北) %"); puts("% 2.B楼 7.耘慧 11.东门 14.体育场(南) %"); puts("% 3.C楼 8.静远 12.南门 %"); puts("% 4.D楼 9.行政 %"); puts("% 5.E楼 %"); puts("% %"); puts(" * * * * * * * * * * * * * * * * * * * * * * * * * * *"); } int creatDN(pDiNetwork &G){ /* 创建有向网 */ FILE * file; int id1,id2,adj; G->vexnum = N; /* 当前边数为14 */ G->arcnum = 0; /* 当前的弧数 */ for (int i = 0; i < G->vexnum; ++i) { G->id[i] = i + 1; /* 初始化建筑id */ for (int j = 0; j < G->vexnum; ++j) G->places[i][j].adj = INFINITY; /* 初始化邻接矩阵 */ } file = fopen("db","r"); /* 读取建筑关系的数据文件 */ while(EOF != fscanf(file,"%d,%d,%d",&id1,&id2,&adj)){ G->places[id1-1][id2-1].adj = adj; /* 邻接矩阵被赋值 */ G->arcnum++; /* 弧数自增 */ } fclose(file); return OK; } void printDN(pDiNetwork & G){ /* 打印有向网邻接矩阵 */ for (int i = 0; i < G->vexnum; ++i) { for (int j = 0; j < G->vexnum; ++j) { printf("%6d ",G->places[i][j]); } printf("\n"); } } void ShortestPath_DIJ(pDiNetwork & G,int v0,PathMatrix P,ShortPathTable D){ int v,w,i,j,min; int final[MAX_PLACE]; // 辅助矩阵,为真表示该顶点到v0的最短距离已求出,初值为假 for(v=0;v<G->vexnum;++v){ final[v]=FALSE; // 设初值 D[v]=G->places[v0][v].adj; // D[]存放v0到v的最短距离,初值为v0到v的直接距离 for(w=0;w<G->vexnum;++w) P[v][w]=FALSE; // 设P[][]初值为FALSE,没有路径 if(D[v]<INFINITY) // v0到v有直接路径 P[v][v0]=P[v][v]=TRUE; // 一维数组p[v][]表示源点v0到v最短路径通过的顶点 } D[v0]=0; // v0到v0距离为0 final[v0]=TRUE; // v0顶点并入S集 for(i=1;i<G->vexnum;++i) // 其余G.vexnum-1个顶点 { // 开始主循环,每次求得v0到某个顶点v的最短路径,并将v并入S集 min=INFINITY; // 当前所知离v0顶点的最近距离,设初值为∞ for(w=0;w<G->vexnum;++w) // 对所有顶点检查 if(!final[w]&&D[w]<min) //在S集之外的顶点中找离v0最近的顶点,并将其赋给v,距离赋给min { v=w; min=D[w]; } final[v]=TRUE; // 将v并入S集 for(w=0;w<G->vexnum;++w) // 根据新并入的顶点,更新不在S集的顶点到v0的距离和路径数组 if(!final[w]&&min<INFINITY&&G->places[v][w].adj<INFINITY&&(min+G->places[v][w].adj<D[w])) { // w不属于S集且v0→v→w的距离<目前v0→w的距离 D[w]=min+G->places[v][w].adj; // 更新D[w] for(j=0;j<G->vexnum;++j) // 修改P[w],v0到w经过的顶点包括v0到v经过的顶点再加上顶点w P[w][j]=P[v][j]; P[w][w]=TRUE; } } /* 迪杰斯特拉算法 */ } void getRoute(pDiNetwork & G, int from, int to){//递归求解 访问记录数组,到达递归出口后回溯. int back; for (int i = 0; i < flag; ++i) /* 出口1:已经访问过 */ if(from == route[i]) return; if(from == to){ /* 出口2:得到一条路线 */ int sum=0; route[flag++]=from; printf("☆ %s", name[route[0]]); for (int i = 1; i < flag; ++i){ sum = sum+G->places[route[i-1]][route[i]].adj; printf("→%s", name[route[i]]); } printf("\n※ 距离%d个单位\n", sum); if (sum<min) { /*如果距离比已记录的距离小*/ int i; min=sum; for (i = 0; i < flag; ++i) path[i] = route[i]; /* 记录最短路线 */ path[i]=-1; /* 标记结束位置 */ } flag--; /* 回溯 */ printf("\n"); return; } route[flag++]=from; /* 递归算法 */ back=flag; for (int i = 0; i < 14; ++i){ if(G->places[from][i].adj!=INFINITY) getRoute(G, i, to); /* 存在路径就递归 递归结束后回溯*/ flag=back; /* 回溯 */ } } int main(void){ int from,to; PathMatrix p; /* 二维数组,路径矩阵 */ ShortPathTable d; /* 一维数组,最短距离表 */ DiNetwork * G = (DiNetwork *)malloc(sizeof(DiNetwork)); /* 申请内存 */ creatDN(G); /* 初始化有向网 */ //printDN(G); /* 打印有向网邻接矩阵 测试用*/ printMenu(); /* 菜单 */ puts("请输入 ps: 6,7 回车"); scanf("%d,%d" ,&from, &to); //求解所有路线和距离 printf("#1. \n从%s到%s共有一下路线选择(递归回溯求解)\n\n", name[from-1], name[to-1]); getRoute(G, from-1, to-1); //求解最短路径(迪杰斯特拉算法) puts("#2. \n最短路径(迪杰斯特拉算法)"); ShortestPath_DIJ(G,from-1,p,d); printf("※ %d个单位\n", d[to-1]); //所求的最短路线 printf("☆ %s", name[route[0]]); for (int i = 1; -1 != path[i] && i < N; ++i){ printf("→%s", name[path[i]]); } printf("\n"); // system("pause"); return 0; }
代码说明:
迪杰斯特拉算法 不是太明白,直接抄书上的.时间比较急,就没有修改.
clion中编译后运行读取文件时老是出现错误,不知道咋回事..sublime编写的代码.
c++语法:用到引用.
我是大二的学生,假如看到不规范的地方,错误的地方麻烦您提出来.
4.运行后的截图
时间: 2024-10-11 22:13:19