1.实验目的

熟练掌握图的操作,掌握 Dijkstra 算法的原理。

2.实验要求

输入:通过命令行参数输入起点和终点的位置名称。

输出:   (1)命令行参数不正确输出ERROR_01;

(2)获取最短路径失败时输出ERROR_02;

(3)获取最短路径成功时输出路径长度。

实际地图

1 右图为校内知名建筑物示意平面图(其中“传送门”用于增加网络复杂度),以边表示建筑物间的路径,各条路径上方的数字表示路径长度。

2 针对该图进行构建数据结构和算法,通过命令行参数输入任意两建筑物的名称,可查询建筑物间的最短路径长度,并输出最短路径。

代码质量要求:

1、优选C语言,禁止直接调用C++ STL库;

2、除循环变量外,其它变量命名使用有明确含义的单词或缩写,不建议使用拼音;

3、禁止出现魔鬼数字;                                        4、添加必要的程序注释;

5、统一代码格式,例如:{}和空行;                    6、变量初始化,不要依赖默认赋值;

7、入参检查,“外部输入输入不可靠”,指针判空(一级指针、二级指针……),循环变量上下限;

8、malloc与free配对;                                       9、尽量少用全局变量;

10、编译错误解决,从前往后处理,提示出错的行不一定是错误的根因;

3.实验原理

图的存储和头文件的引入:

为了使得代码可以被重复使用,即代码被二次利用时只需要更改图的模式识别代码,同时改变宏定义之中的最大次数,本次将图的文件和宏定义的部分单独的写成一个头文件,在书写主程序时对他进行引用即可。

#ifndef      _COMMON_H//和文件名一致,将.换成_;前面加_。

#define     _COMMON_H//避免重复声明,使用if no define,define......endif

#include<stdio.h>//添加程序所需要的所有头文件

#include<string.h>

#define Status int//添加宏定义部分

static int a = 0 ;//可以定义静态变量,在所有.c文件中使用。

extern int  test(char* p,int n)//声明所有子函数

#endif

迪杰特斯拉算法思想:

设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

具体步骤:

(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。

(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。

(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。

(4) 重复步骤(2)和(3),直到遍历完所有顶点。

简明实例:

4.实验结果

5.问题与思考

思考:

对于Git的使用和一些其他的东西了解的不够深刻,对于编译器编译过程的理解依然不够深刻,这些都需要后续的学习去加以提升。

#.h文件

#pragma once
#ifndef _HEAD_H_
#define _HEAD_H_
#define InAccessible   100000       //无法抵达时的总长度
#define Status int
#define OK 2
#define TRUE 1
#define change 1                    //用于扩大1位,进行占位和存放
#define FALSE 0
#define PLen 0
#define none -1
#define ERROR -1                    //用于判定是否出现错误
#define OVERFLOW -2                 //用于判断是否分配成功
#define ERROR_01 -3                 //入参不正确
#define ERROR_02 -4                 //无法生成虽短路径
#define MaxNum 20                   //最大支持的存放的节点数目//图的数据结构
typedef struct GRAPH
{int vexs[MaxNum];              //定义结点矩阵,用于存放所有的结点int arcs[MaxNum][MaxNum];      //定义邻接矩阵,用于之后的计算和分析int vexnum;                       //总的节点数目int arcnum;                     //总的边的数目
}Graph;                             //图的结构体的名称//所有的地点名称及其所对应的在图中顶点的脚标
extern const char* PlaceName[13] = { "北门","饮水思源","传送门3","传送门1","腾飞塔","图书馆","传送门2","传送门4","教学主楼","宪梓堂","西迁馆","活动中心","南门" };//0        1          2         3         4        5        6         7         8         9         10       11       12//对图片进行初始化
extern Status InitMap(Graph* map)
{if (!map) return ERROR;                                    //鲁棒性检测map->vexnum = 13;                                        //所有结点的个数map->arcnum = 18;                                      //所有边的条数//初始化所有的结点和边int i = 0, j = 0;             for (i = 0; i < map->vexnum; ++i) {map->vexs[i] = i;for (j = 0; j < map->vexnum; ++j)                 //对角线上初始化为0if (i == j) map->arcs[i][j] = 0;else {map->arcs[i][j] = InAccessible;              //全部先初始化为不连通}}//初始化邻接矩阵map->arcs[0][2] = map->arcs[2][0] = 22;map->arcs[0][1] = map->arcs[1][0] = 18;map->arcs[1][3] = map->arcs[3][1] = 27;map->arcs[1][4] = map->arcs[4][1] = 19;map->arcs[4][2] = map->arcs[2][4] = 4;map->arcs[4][7] = map->arcs[7][4] = 32;map->arcs[3][5] = map->arcs[5][3] = 4;map->arcs[5][6] = map->arcs[6][5] = 4;map->arcs[4][5] = map->arcs[5][4] = 23;map->arcs[5][8] = map->arcs[8][5] = 15;map->arcs[8][11] = map->arcs[11][8] = 21;map->arcs[11][12] = map->arcs[12][11] = 30;map->arcs[7][9] = map->arcs[9][7] = 4;map->arcs[8][9] = map->arcs[9][8] = 8;map->arcs[6][12] = map->arcs[12][6] = 21;map->arcs[6][10] = map->arcs[10][6] = 43;map->arcs[10][12] = map->arcs[12][10] = 20;map->arcs[9][12] = map->arcs[12][9] = 14;return OK;
}
extern Graph;
#endif

#.cpp文件

/*寻找图片中的最小路径的问题,张文硕-2206110686-自动化03*/#include<stdio.h>     //调用内部包
#include<malloc.h>        //调用内存分配文件包
#include<string.h>
#include "map.h"      //调用map文件,其中存放了图的基本信息和宏定义信息,方便之后对图片文件进行跟换,只需更改InitMap即可。typedef int PathMatrix[MaxNum][MaxNum+change];      //定义路径矩阵
typedef struct {int weight[MaxNum];                             //定义最短路径长度和Status Visited[MaxNum];                          //定义列表标记是否被访问过
}ShortPathList;//判断入参数量是否正确
//如果参数为3,        则认为没有错误
//如果参数不为3,   则认为有错误
Status IfError_01(int argc)
{if (argc == 3) return FALSE;else {printf("ERROR_01");return TRUE;}
}//寻找输入的地点在地点列表中的位置
//如果找到了,则返回下标
//如果找不到,则返回ERROR_02
int FindPlace(const char* PlaceName[], char* name,Graph* map)
{if (!PlaceName || !name|| !map) return ERROR;                  //鲁棒性检测int i = 0;while (i < map->vexnum)                                         //进行寻址{if (strcmp(PlaceName[i], name) == 0) return i;i++;}printf("ERROR_02");                                             //当跳出循环还没返回答案时,认为出错了return ERROR_02;
}//定义函数初始化最短路径列表
//所有visit状态更新为FALSE
//所有权重进行处理,除自己到自己之外全部为无穷大,方便之后修改
Status InitList(ShortPathList* List,Graph map,int start)
{if (!List) return ERROR;for (int i = 0; i < map.vexnum; i++){List->Visited[i] = FALSE;List->weight[i] = InAccessible;}List->weight[start] = 0;return OK;
}
//功能:让path矩阵的每行第一列表示路径长度.
//每行第一列全部初始化为FALSE
Status InitPath(PathMatrix& path,Graph map,int start)
{if (!path) return ERROR;for (int i = 0; i < map.vexnum; i++){for (int j = 0; j < map.vexnum + change; j++){path[i][j] = none;                        //将所有的长度初始化为-1}}path[start][0] = 1;path[start][1] = start;return OK;
}
//功能:更新路径,使得路径更小
//输入:使得路径更新为到起点距离更小的路径,更小路径结点横坐标为now,原先的路径横坐标结点为before
//输出:状态
Status UpdatePath(PathMatrix &path,int before,int now,Graph map)
{if (!path) return ERROR;for (int i = 0; i < map.vexnum; i++){path[before][i] = path[now][i];                //将小的直接抄过来}return OK;
}//功能:修改结点到起点的路径长度最小值,并调用函数UpdatePath更新每个结点的最短路径。
//结果:如果新的长度小于原有长度,则进行更新。跟新后最后一个结点路径指向被更新的结点。
//                                           总的长度进行加一运算,同时对权重也进行更新。
Status ChangeWeight(Graph map, ShortPathList* list, int curnode, PathMatrix& path)
{if (!list||!path) return ERROR;for (int i = 0; i < map.vexnum; i++){if (list->Visited[i] == FALSE){if (list->weight[i] > list->weight[curnode] + map.arcs[curnode][i]){UpdatePath(path, i, curnode,map);                                      //当满足条件时更新路径path[i][PLen]++;                                                          //总的路径长度path[i][0]加一path[i][path[i][PLen]] = i;                                                //最后一步补上当前的位置list->weight[i] = list->weight[curnode] + map.arcs[curnode][i];            //将权重更新为较小的值}}}return OK;
}
//功能:寻找最短的路径的结点并修改访问状态
//输入:list存放有每个节点到起点的距离;map用于存放图的信息
//输出:最小的所处的位置;
int FindShort(ShortPathList* list,Graph map)
{if (!list) return ERROR;int shortest=none;int flag = TRUE;int i = 0;while ( i < map.vexnum && flag)                              //寻找第一个未被访问的结点{if (list->Visited[i] == FALSE){shortest = i;flag =FALSE;}i++;}for (int i = 0; i < map.vexnum; i++)                        //寻找所有节点中未被访问的最小长度结点{if (list->Visited[i] == FALSE){if (list->weight[i] < list->weight[shortest]){shortest = i;}}}//if (shortest != none) list->Visited[shortest] = TRUE;       //更改访问状态return shortest;                                            //返回角标,如果角标是none,认为所有都访问完了,可以给结果了
}
//函数功能:求出指定起点到终点的最短路径,并且存放最短路径
/*输入:map     已经初始化完成的有向图start    起点序号end     终点序号list    存放最短路径长度的数组path 用于记录脚步的返回值:返回从start到end的最短路径权值*/
int DJT_ShortPath(Graph map, PathMatrix& path, ShortPathList* list, int start, int end)
{if (!path || ! list) return ERROR;InitList(list,map,start);InitPath(path, map,start);int cursor;while (FindShort(list, map) != none){cursor = FindShort(list, map);list->Visited[cursor] = TRUE;ChangeWeight(map, list, cursor, path);}return list->weight[end];
}Status PrintPath(PathMatrix path, int end,const char** PlaceName)
{if (!PlaceName) return ERROR;int flag = TRUE;for (int i = 0; i < path[end][0]; i++){if (flag){printf("\n%s", PlaceName[path[end][i + change]]);flag = FALSE;}else{printf("->%s", PlaceName[path[end][i + change]]);}}return OK;
}
int main(int argc, char* argv[])
{if(IfError_01(argc)) return ERROR_01;Graph* map = (Graph*)malloc(sizeof(Graph));if (!map) return OVERFLOW;InitMap(map);PathMatrix path = { none };                                                       //定义记录路径的矩阵ShortPathList* list=(ShortPathList*) malloc(sizeof(ShortPathList));             //定义所有结点到起点的路径长度,if (!list) return OVERFLOW;                             int start = FindPlace(PlaceName, argv[1], map);            //起始地点的坐标if (start == ERROR_02) return ERROR_02;int end = FindPlace(PlaceName, argv[2], map);            //终止地点的坐标if (end == ERROR_02) return ERROR_02;int shortestdistance = 0;shortestdistance=DJT_ShortPath(*map, path, list, start, end);                    //寻找最小路径长度并将其存放进shortestdistanceprintf("%d", shortestdistance);//PrintPath(path,end,PlaceName);free(map);                                                                     //释放map指针free(list);                                                                        //释放list指针return 0;
}

实验四:无向图最短路径搜索相关推荐

  1. java用十字链表实现无向图_实验四:图的实现与应用

    20162317袁逸灏 实验四:图的实现与应用 实验内容 用 邻接矩阵 十字链表 实现无向图中的 添加结点 删除结点 添加边 删除边 size() isEmpty() 广度优先迭代器 深度优先迭代器 ...

  2. 无人驾驶汽车系统入门(十六)——最短路径搜索之A*算法

    无人驾驶汽车系统入门(十六)--最短路径搜索之A*算法 路线规划中一个很核心的问题即最短路径的搜索,说到最短路径的搜索我们就不得不提A*算法,虽然原始的A*算法属于离散路径搜索算法(我们的世界是连续的 ...

  3. 测试地图最短路径搜索(二):换个稍微复杂点的路径模板

    工具点此链接. 点击这里看下前面介绍的这种方案的基本原理. 测试地图最短路径搜索(一):把所有的辅助条件都铺到地图上 测试地图最短路径搜索(二):换个稍微复杂点的路径模板 测试地图最短路径搜索(三): ...

  4. C语言 操作系统实验 四种调度(最高响应比优先算法 HRN)

    注: 本文是四个调度算法的第一篇算法. 本文是根据CSDN上某一FCFS调度算法魔改来的,所以FCFS的算法不会发到网站. 我是个菜鸡,发文是为了纪念自己完成了代码,以及累计自己的经验. 如有知识错误 ...

  5. 2017-2018 20162329 张旭升 实验报告:实验四

    实验四:图及应用 课程:程序设计与数据结构 班级: 1623 姓名: 张旭升 学号:20162329 指导教师:娄嘉鹏 王志强 实验日期:11月22日 实验密级: 非密级 预习程度: 已预习 必修/选 ...

  6. 深大算法实验四——流水线问题

    代码链接:深大算法实验四--车间动态规划代码-C++文档类资源-CSDN下载 目录 实验目的与要求: 实验过程及内容: 蛮力法: 动态规划法: 改进 空间优化方案: 问题1,关于最优解的存储方案 问题 ...

  7. 2017-2018-2 20165236 实验四《Android开发基础》实验报告

    2017-2018-2 20165236 实验四<Android开发基础>实验报告 一.实验报告封面 课程:Java程序设计       班级:1652班       姓名:郭金涛     ...

  8. python实训总结报告书_20172304 实验四python综合实践报告

    20172304 实验四python综合实践报告 姓名:段志轩 学号:20172304 指导教师:王志强 课程:Python程序设计 实验时间:2020年5月13日至2020年6月14日 实验分析 本 ...

  9. matlab 迭代 混沌与分形实验报告,实验四 函数的迭代混沌与分形.doc

    实验四 函数的迭代混沌与分形.doc 实验四函数的迭代.混沌与分形实验目的1认识函数的迭代:2了解混沌和分形迭代在数值计算中占有很重要的地位,了解和掌握它是很有必要的本实验将讨论用NEWTON迭代求方 ...

最新文章

  1. java设置可信任站点_通过网页修改activex安全设置,添加信任站点,禁用弹出窗口阻止程序...
  2. ES6新增的let与const
  3. 元数据驱动设计 —— 为动态移动应用创建Web API
  4. linux gcc 与 glibc 的关系 glibc版本查看
  5. Linux内核中的platform机制
  6. php中静态方法的调用,php中静态方法和非静态方法如何相互调用?
  7. ubuntu copy命令
  8. 浅谈javascript的面向对象(OOP)
  9. 多线程之线程通信条件Condition
  10. Android面试心得,已拿到字节跳动,京东,android应用开发基础学堂在线答案
  11. Qt语言家使用中遇到的问题及解决方案
  12. 网页设计语言html做思维导图,web网页实现思维导图展示
  13. 深入浅出计算机组成原理(四)——穿越功耗墙,我们该从哪些方面提升“性能”?
  14. 物流公司的发出时间在哪里查询,快递单号查询方法
  15. 重走来时路,这一次我会披荆斩棘
  16. FAF世链区块链大会|赤兔云算CTO 杨钧淏:共建区块链生态,创造新财富时代
  17. 测试与开发人员的战斗
  18. “打折”上市的网易云音乐一跌再跌,为何资本市场不买单?
  19. java+selenium,40行代码完成支付宝账单爬取
  20. 中科创达发布融合智能泊车技术于解决方案

热门文章

  1. MUR1060AC-ASEMI快恢复二极管10A 600V
  2. 阅文集团 php,腾讯开源|腾讯与阅文技术合作 微服务框架Tars再添PHP
  3. 【NOIP2011模拟11.1】钓鱼
  4. 如何快速对比两个文件夹的文件的不同
  5. Isometric Tile
  6. Python练习笔记 - - 句子翻转
  7. 常用的Python标准库有哪些
  8. Python修改文件的后缀名
  9. 【Medium Python】第三话:python多线程为什么不能并行?
  10. 如何给自己各种帐号编一个安全又不会忘记的密码?