交通网查询系统

基于图的数据结构实现的交通网查询系统

  • 需求分析
    问题描述:交通网查询系统的业务活动包括:添加城市信息、删除城市信息、修改城市信息、查询城市间路线等,通过图的数据结构来设计一个交通查网询系统,以使上述业务可以借助计算机来完成。

  • 实现情况:采用图的数据结构,实现了中国交通网查询系统对于站点的增删改查功能。增:添加新的城市站点,根据经纬度的控制将其范围限制在中国境内;根据经纬度判断城市间实际路线长度,以此判断添加城市与其他城市间的关系是否符合实际情况。删:通过名称找到站点,删除站点以及站点和其他城市间的所有关系。改:可以改变城市间的关系以及城市本身的信息,例如站点开关,站点经纬度等。查:利用无向图位权图之间的查询方法,可以找到最短路径、最优价格方案、以及城市间所有的路线关系。显示:采用图形界面与用户交互,通过监控鼠标来控制。

  • 编程环境:VS

  • 编程语言:C语言

概要设计

  • 所要用到的标准函数库文件
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
#include <queue>
#include<easyx.h>
#include<time.h>
#include<stdint.h>
#include <stddef.h>
  • 自定义的头文件
#include "Insert_Functions.h"
#include "Search_Functions.h"
#include "Modify_Functions.h"
#include "Delete_Functions.h"
#include "Insert_Print_Info.h"
#include "Search_Print_Info.h"
#include "Modify_Print_Info.h"
#include "Delete_Print_Info.h"
#include "Display.h"
  • 图的结构体:
typedef struct {
	int n, e;				//点数和边数
	int arcs[N][N];			//点到点是否有相连关系
	double distance[N][N];	//点到点之间的距离
	char name[N][M];		//第i个点的名字
	int statement[N];		//站点是否开放
	double longtitude[N];	//经度
	double latitude[N];		//纬度
    double money[N][N];		//两点间价格
}MGraph;
  • 数据宏定义
#define option_x 650
#define insert_x 650
#define insert_y 100
#define delete_x 650
#define delete_y 150
#define modify_x 650
#define modify_y 200
#define inquire_x 650
#define inquire_y 250
#define quit_x 650
#define quit_y 300
#define Length_cityname 20
#define modifyrelation_y 100
#define modifydistance_y 150
#define modifymoney_y 200
#define modifyopen_y 250
#define modifyname_y 300
#define modifylongtitude_y 350
#define modifylatitude_y 400
#define modifyquit_y 450
#define searchmindistance_y 100
#define searchminmoney_y 150
#define searchallroad_y 200
#define searchquit_y 250
  • 定义常量
const int INF = 0x3f3f3f3f;
const int N = 110;
const int M = 20;
const double eps = 1e-6;	//机器零
  • 定义背景图
static IMAGE background;//背景
static IMAGE china;//中国轮廓图

程序模块

  • 程序模块流程图:

流程图

  • 方法函数接口

    • 删除模块底层接口
      int Delete_k(MGraph& G, int k);//删除第k个而且总个数自动减1
      
    • 插入模块底层接口
    	int Insert_n(MGraph& G);//添加后点数加1,边数加2
    	int Insert_arcs(MGraph& G, int i, int j);//添加i和j之间的关系
    	int Insert_distance(MGraph& G, int i, int j, double dist);//添加i和j之间的距离
    	int Insert_money(MGraph& G, int i, int j, double money);//添加i和j之间的价格
    	int Insert_name(MGraph& G, int i, char name[]);//第i个名字的插入
    	int Open_statement(MGraph& G, int i);//开放第i个站点
    	int Close_statement(MGraph& G, int i);//关闭第i个站点
    	int Insert_longtitude(MGraph& G, int i, double num);//第i个站点插入经度
    	int Insert_latitude(MGraph& G, int i, double num);//第i个站点插入维度
    	```
    
    
  • 修改模块底层接口

    int Modify_arcs(MGraph& G, int i, int j, int k);//修改i和j之间的直接联系,边数减2
    int Modify_distance(MGraph& G, int i, int j, double dist);//修改两站之间的距离
    int Modify_money(MGraph& G, int i, int j, double money);//修改i和j之间的价格
    int Modify_name(MGraph& G, int i, char name[]);//第i个点名字修改
    int Modify_longtitude(MGraph& G, int i, double num);//修改第i个站点经度
    int Modify_latitude(MGraph& G, int i, double num);//修改第i个站点维度
    int Mopen_statement(MGraph& G, int i);//开放第i个站点
    int Mclose_statement(MGraph& G, int i);//关闭第i个站点
    
  • 查询模块底层接口

    //求所有最短路径
    int ShortestPath_Floyd(MGraph G, double d[N][N]); 
    //path[N]存放路径,visited[N]存放是否遍历该点, v是起点(使用直接调用Find_Short_road函数)
    void Dijkstra(MGraph G, int v, int path[], int visited[]);
    //输入起点和终点,然后下标的先后顺序存放在road数组中(1开始存放)(直接开road)
    int Find_Short_road(MGraph G, int begin, int end, int road[]);
    //配合Find_All_Road函数使用(直接调用Find_All_Road函数)
    void DFS_road(MGraph G, int visited[], int begin, int end, int path[], double dist, int t, int a[N][N], int& cnt, double b[]);
    //查询符合方案的所有路径,递归 
    int Find_All_Road(MGraph G, int begin, int end, int a[N][N], double b[]);
    //配合Find_All_Money函数使用(直接调用Find_All_money函数)
    void DFS_money(MGraph G, int visited[], int begin, int end, int path[], double pay, int t, int a[N][N], int& cnt, double b[]);
    //查询符合方案的所有花费,递归
    int Find_All_Money(MGraph G, int begin, int end, int a[N][N], double b[]);
    //path[N]存放路径,visited[N]存放是否遍历该点, v是起点(使用直接调用Find_Minimum_cost函数)
    void Dijkstra_money(MGraph G, int v, int path[], int visited[]);
    //输入起点和终点,然后下标的先后顺序存放在road数组中(1开始存放)(直接开road)
    int Find_Minimum_cost(MGraph G, int begin, int end, int road[]);
    //配合Find_All函数使用(直接调用 Find_All)函数)
    void DFS_All(MGraph G, int visited[], int begin, int end, int path[], double dist, double pay, int t, int a[N][N], int& cnt, double b[], double c[]);
    //所有下标从1开始
    //输入起点begin终点end和一个存放二维数组(直接开a[N][N]),然后所有方案放在二维数组,一行为一个方案,列数为所有方案
    //一个存放距离的值(直接开b[N])存放对应行数的距离
    //一个存放花费的是c[N]存放对应行数的花费
    int Find_All(MGraph G, int begin, int end, int a[N][N], double b[], double c[]);
    //查询站点状态
    int Check_Station(MGraph G, int i);
    
  • 实现函数接口

    • 删除模块的信息输出功能实现

      void deleteCityMessage(MGraph& G);
      
    • 插入模块的信息输出功能

    void insertCityMessage(MGraph& G);
    wchar_t GetInput();
    
    • 修改模块的信息输出功能实现
    void modifyCityRelation(MGraph& G);
    void modifyCityDistance(MGraph& G);
    void modifyCityMoney(MGraph& G);
    void modifyCityOpen(MGraph& G);
    void modifyCityName(MGraph& G);
    void modifyCityLongtitude(MGraph& G);
    void modifyCityLatitude(MGraph& G);
    
    • 查询模块的信息输出功能实现
    void searchMinDistanceRoad(MGraph& G);
    char* join1(char* a, char* b);
    double change(MGraph G, double num, int classes);
    void searchMinCostRoad(MGraph& G);
    void findAllRoad(MGraph& G);
    
    • 地图模块的信息输出功能实现
    void menu(MGraph &G);
    //找到名字返回下标,否则返回-1
    int find_name(MGraph& G, char name[]);
    int InitMGraph(MGraph& G);
    void displayCity(MGraph G);
    void drawMainMenu(MGraph G);
    void modifyCityMessage(MGraph& G);
    void searchCityMessage(MGraph& G);
    void drawline(MGraph& G, int road[]);
    

用户手册及测试结果

  • 系统说明:
    用户界面根据图形界面输出,直观且美观,根据监控鼠标来判断用户选择什么功能(即通过鼠标点击控制选择对应模块),用户交互界面直观。

  • 交通网初始界面:
    在这里插入图片描述

  • 点击鼠标控制选择功能模块
    点击进入添加模块
    在这里插入图片描述

  • 点击删除城市信息进入删除模块
    在这里插入图片描述

  • 点击修改城市信息进入修改模块
    修改模块包含7个子模块
    在这里插入图片描述

  • 点击进入查询路线功能

在这里插入图片描述

调试分析

(1) 删除时,删除掉某个站点后,站点个数减一,而导致最后一个站点丢失,解决方法是将站点前移(将后面数据上移和左移)
(2) 判断参数时,当数据为double类型时,应和机器零做比较
(3) 路径判断时,未对站点开关进行判断,从而导致站点关闭也会存在相应路径;解决方法,加入站点判断函数,进行控制路径查找。
(4) 当站点关闭或者开启时,未在地图上标明,地图上无法直观看出站点状态。解决方法:当站点关闭时,图标显示蓝色,开启时显示红色。

部分源码展示

//Delete_Functions.cpp
#include"Map.h"
//删除模块的实现功能
//删除第k个而且总个数自动减1
int Delete_k(MGraph& G, int k) {
	if (k < 1 || k > G.n)	return false;//非法输入

    for(int i = 1 ; i <= G.n ; i ++ )
        if(G.arcs[k][i])
            G.e -= 2;

	//左上为坐标零点,向右为i,向下为j,利用稍微开大的数组
	// 在数据移动的时候同时也做了初始化边界操作
	// 因此,在后续操作中G.n的大小必须满足
	//				G.n < N
	
	//先从把后面的数据上移
	for (int i = k; i <= G.n; i++) {
		for (int j = 1; j <= G.n; j++) {
			G.arcs[i][j] = G.arcs[i + 1][j];
			G.distance[i][j] = G.distance[i + 1][j];
			memcpy(G.name[i], G.name[i + 1], sizeof G.name[i + 1]);
			G.statement[i] = G.statement[i + 1];
			G.longtitude[i] = G.longtitude[i + 1];
			G.latitude[i] = G.latitude[i + 1];
			G.money[i][j] = G.money[i + 1][j];
		}
	}
	//先从把后面的数据左移
	for (int i = 1; i <= G.n; i++) {
		for (int j = k; j <= G.n; j++) {
			G.arcs[i][j] = G.arcs[i][j + 1];
			G.distance[i][j] = G.distance[i][j + 1];
			G.money[i][j] = G.money[i][j + 1];
		}
	}
	G.n--;
	return true;
}

//修改i和j之间的直接联系
int Modify_arcs(MGraph& G, int i, int j,int k) {//参数k存放两点之间关系,0表示修改成无联系,1表示修改成有联系
	if (i < 1 || i > G.n || j < 1 || j > G.n)	return false;//非法输入
	if (k != 0 || k != 1) return false;//非法参数
	if (k == 1) {
		if (k == G.arcs[i][j]) {
			return true;
		}
		else {
			G.e += 2;
			G.arcs[i][j] = G.arcs[j][i] = 1;
		}
	}
	if (k == 0) {
		if (k == G.arcs[i][j]) {
			return true;
		}
		else {
			G.e -= 2;
			G.arcs[i][j] = G.arcs[j][i] = 0;
		}
	}
	return true;
}

//修改两站之间的距离
int Modify_distance(MGraph& G, int i, int j, double dist) {
	if (i < 1 || i > G.n || j < 1 || j > G.n)	return false;
	if (dist < 0)	return false;//非法输入

	G.distance[i][j] = G.distance[j][i] = dist;
	return true; 
}

//修改i和j之间的价格
int Modify_money(MGraph& G, int i, int j, double money) {
	if (i < 1 || i > G.n || j < 1 || j > G.n) return false;
	if (money < 0) return false;//非法输入
	G.money[i][j] = G.money[j][i] = money;
	return true;
}

//第i个点名字修改
int Modify_name(MGraph& G, int i, char name[]) {
	if (i < 1 || i > G.n)	return false;//非法输入
	if (sizeof(name) > M) return false;//非法输入,参数过长
	memcpy(G.name[i], name, sizeof name);
	return true;
}

//修改第i个站点经度
int Modify_longtitude(MGraph& G, int i, double num) {
	if (i < 1 || i > G.n)	return false;
	if (num < 73.33 || num > 135.05)	return false;
	G.longtitude[i] = num;
	return true;
}

//修改第i个站点维度
int Modify_latitude(MGraph& G, int i, double num) {
	if (i < 1 || i > G.n)	return false;
	if (num < 3.51 || num > 53.33)	return false;
	G.latitude[i] = num;
	return true;
}

//开放第i个站点
int Mopen_statement(MGraph& G, int i) {
	G.statement[i] = 1;
	return true;
}

//关闭第i个站点
int Mclose_statement(MGraph& G, int i) {
	G.statement[i] = 0;
	return false;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值