数据结构之图及其应用
一,目的
-
掌握图的存储、构建、搜索等操作和应用,能用最短路径及其搜索等算法编制较综合性的程序,求解最优路线问题,进行程序设计、数据结构和算法设计等方面的综合训练。
-
设计一个城市交通咨询模拟系统,利用该系统实现至少两种最优决策:最短路程到达、最省时到达等线路规划。
二,描述
用户驾车出行由于出行目的的不同对道路路线选择的要求也有不同。例如,有的希望在途中的路程尽可能短,有的则可能希望路程中时间最短。为了能满足广大旅客的需求,编制一个城市交通咨询模拟系统,选取城市部分位置、道路抽象为程序所需要图的顶点和边,并以城市道路长度(路程),道路的某时段的速度等信息作为图结点中的弧信息,为旅客提供这两种最优决策的交通咨询。
输入和输出:
(1)输入形式:
构建图时,输入顶点、弧涉及的信息,包括:起始地、目的地、长度、该弧此时间段的平均速度等信息;
用户或者客户要输入出发地和目的地,并选择何种最优决策的路线规划。
(2)输出形式:根据用户需求输出对应信息
输出最短路程所需要的路线信息和最短路程;
输出最短时间所需要的路线信息和最短时间。
三,代码测试
四,部分源码
-
主要数据类型与变量
typedef struct{ bool visit = false; double value = 0; double time = 0; string path = ""; }Dis; typedef struct{ int vexnum; //图的顶点个数 int edge; //图的边数 double **arc; //路程邻接矩阵 double **arc1; //时间邻接矩阵 Dis * dis; //记录各个顶点最短路径的信息 Dis * dis1; //记录各个顶点最短时间的信息 }Graph;
-
部分函数模块
//检验输入边数和顶点数的值是否有效 bool check(int Vexnum, int edge); //构造函数 void Graph_DG(int vexnum, int edge, Graph &H) { //为邻接矩阵开辟空间和赋初值 H.edge = edge; H.vexnum = vexnum; H.arc = new double*[vexnum]; H.arc1 = new double*[vexnum]; H.dis = new Dis[vexnum]; H.dis1 = new Dis[vexnum]; for (int i = 0; i < vexnum; i++) { H.arc[i] = new double[vexnum]; for (int k = 0; k < vexnum; k++) { //邻接矩阵初始化为无穷大 H.arc[i][k] = INT_MAX; } } for (int i = 0; i < vexnum; i++) { H.arc1[i] = new double[vexnum]; for (int k = 0; k < vexnum; k++) { //邻接矩阵初始化为无穷大 H.arc1[i][k] = INT_MAX; } } } // 判断我们每次输入的的边的信息是否合法,顶点从1开始编号 bool check_edge_value(int start, int end, int weight, Graph H); //创建图 void createGraph(Graph &H) { cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其长度和平均速度" << endl; int start; int end; double weight; double speed; int count = 0; while (count != H.edge) { cin >> start >> end >> weight >> speed; //首先判断边的信息是否合法 while (!check_edge_value(start, end, weight, speed, H)) { cout << "输入的边的信息不合法,请重新输入" << endl; cin >> start >> end >> weight >>speed; } //对邻接矩阵对应上的点赋值 H.arc[start - 1][end - 1] = weight; H.arc1[start - 1][end - 1] = weight/speed; ++count; } } //打印邻接矩阵 void print(Graph H); //求最短路径 void Dijkstra1(Graph H, int begin){ //首先初始化我们的dis数组 int i; for (i = 0; i < H.vexnum; i++) { //设置当前的路径 H.dis1[i].path = "v" + to_string(begin) + "-->v" + to_string(i + 1); H.dis1[i].value = H.arc1[begin - 1][i]; } //设置起点的到起点的路径为0 H.dis1[begin - 1].value = 0; H.dis1[begin - 1].visit = true; int count = 1; //计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点) while (count != H.vexnum) { //temp用于保存当前dis数组中最小的那个下标 //min记录的当前的最小值 int temp=0; int min = INT_MAX; for (i = 0; i < H.vexnum; i++) { if (!H.dis1[i].visit && H.dis1[i].value<min) { min = H.dis1[i].value; temp = i; } } //cout << temp + 1 << " "<<min << endl; //把temp对应的顶点加入到已经找到的最短路径的集合中 H.dis1[temp].visit = true; ++count; for (i = 0; i < H.vexnum; i++) { //注意这里的条件H.arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常 if (!H.dis1[i].visit && H.arc1[temp][i]!=INT_MAX && (H.dis1[temp].value + H.arc1[temp][i]) < H.dis1[i].value) { //如果新得到的边可以影响其他为访问的顶点,那就就更新它的最短路径和长度 H.dis1[i].value = H.dis1[temp].value + H.arc1[temp][i]; H.dis1[i].path = H.dis1[temp].path + "-->v" + to_string(i + 1); } } } } void print_path(Graph H, int begin);//打印最短路径 void Dijkstra1(Graph H, int begin);//初始化我们的dis数组 void print_path1(Graph H, int begin); //打印最短时间
主函数
int main() { int vexnum; int edge; cout << "输入图的顶点个数和边的条数:" << endl; cin >> vexnum >> edge; while (!check(vexnum, edge)) { cout << "输入的数值不合法,请重新输入" << endl; cin >> vexnum >> edge; } Graph H; Graph_DG(vexnum, edge, H); createGraph(H); // print(H); Dijkstra(H, 1); print_path(H, 1); Dijkstra1(H, 1); print_path1(H, 1); system("pause"); return 0; }