安徽大学导游系统设计---迪杰斯特拉算法实现

本文是基于《数据结构》相关实验,使用迪杰斯特拉算法来实现最短路径。

总体思路是对于安徽大学磬苑校区进行数学建模,对重要的景点进行抽象。抽象成无向图中间的顶点。之后利用高德地图对各个顶点之间测距。

6dd1a7b57512437d9011299032fca914.jpeg

废话不多说,之后上代码:

首先是初始的一些操作,图和顶点的相关定义:

#define _CRT_SECURE_NO_WARNINGS
#define INFINTY 10000
#define v 20
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct 
{
	int number;
	char name[100];
	char info[100];
}VertexType; //顶点结构

typedef struct {
	VertexType vexs[20];
	int arcs[20][20];//邻接矩阵
	int vexnum, arcnum;//顶点个数,边的个数 
}MGraph; //图结构

之后手动录入相关景点和边的数据:

void CreateGraph(MGraph &G)
{
	int i,j;
    G.vexnum = 16;
	for (i = 0; i < 16; i++)
	{//初始化路径长度均为0
		for (j = 0; j < 16; j++)
		{
			G.arcs[i][j] = 0;
		}
	}
    strcpy(G.vexs[0].name, "体育馆");
    strcpy(G.vexs[1].name, "北体育场");
    strcpy(G.vexs[2].name, "杏园宿舍");
    strcpy(G.vexs[3].name, "篮球场");
    strcpy(G.vexs[4].name, "理工楼D");
    strcpy(G.vexs[5].name, "橘园食堂");
    strcpy(G.vexs[6].name, "博学北楼");
    strcpy(G.vexs[7].name, "西门");
    strcpy(G.vexs[8].name, "鸣磬广场");
    strcpy(G.vexs[9].name, "文典阁");
	strcpy(G.vexs[10].name, "磬苑广场");
	strcpy(G.vexs[11].name, "笃行南楼");
	strcpy(G.vexs[12].name, "孔子像");
	strcpy(G.vexs[13].name, "桂园食堂");
	strcpy(G.vexs[14].name, "行政楼");
	strcpy(G.vexs[15].name, "南体育场");
    strcpy(G.vexs[0].info, "体育馆可以打羽毛球,做核酸");
    strcpy(G.vexs[1].info, "北体育场可以踢足球,有看台");
    strcpy(G.vexs[2].info, "杏园宿舍和枣园和榴园宿舍都是学生的宿舍");
    strcpy(G.vexs[3].info, "篮球比赛进行的地方");
    strcpy(G.vexs[4].info, "计算机科学与技术学院");
    strcpy(G.vexs[5].info, "烤鸭饭,瑞辛咖啡,蜜雪冰城");
    strcpy(G.vexs[6].info, "基础课专业课教学楼和自习教室");
    strcpy(G.vexs[7].info, "安徽大学人流量最大的进出口");
    strcpy(G.vexs[8].info, "晚上有乐队的演出");
    strcpy(G.vexs[9].info, "图书馆,很多藏书,可以自习,考研圣地");
	strcpy(G.vexs[10].info, "喷泉和安徽大学的标志,旁边有行知楼");
	strcpy(G.vexs[11].info, "计算机实验室和化学实验室");
	strcpy(G.vexs[12].info, "孔子的雕像,旁边是新闻传播学院");
	strcpy(G.vexs[13].info, "安徽大学最好吃的食堂,没有之一");
	strcpy(G.vexs[14].info, "政务处理,教学办");
	strcpy(G.vexs[15].info, "足球场和篮球场和跑道");
    G.arcs[0][1] = G.arcs[1][0] =235;
	G.arcs[1][2] = G.arcs[2][1] =220;
	G.arcs[2][3] = G.arcs[3][2] =130;
	G.arcs[1][3] = G.arcs[3][1] =200;
	G.arcs[1][4] = G.arcs[4][1] =320;
	G.arcs[3][4] = G.arcs[4][3] =210;
	G.arcs[2][5] = G.arcs[5][2] =240;
	G.arcs[3][6] = G.arcs[6][3] =325;
	G.arcs[4][10] = G.arcs[10][4] =400;
	G.arcs[5][6] = G.arcs[6][5] =350;
	G.arcs[6][10] = G.arcs[10][6] =220;
	G.arcs[7][8] = G.arcs[8][7] =180;
	G.arcs[8][9] = G.arcs[9][8] =190;
	G.arcs[9][10] = G.arcs[10][9] =345;
	G.arcs[5][8] = G.arcs[8][5] =310;
	G.arcs[5][9] = G.arcs[9][5] =330;
	G.arcs[6][9] = G.arcs[9][6] =210;
	G.arcs[6][10] = G.arcs[10][6] =200;
	G.arcs[11][12] = G.arcs[12][11] =300;
	G.arcs[9][11] = G.arcs[11][9] =150;
	G.arcs[10][11] = G.arcs[11][10] =300;
	G.arcs[10][12] = G.arcs[12][10] =170;
	G.arcs[11][13] = G.arcs[13][11] =225;
	G.arcs[12][13] = G.arcs[13][12] =270;
	G.arcs[8][13] = G.arcs[13][8] =485;
	G.arcs[14][13] = G.arcs[13][14] =530;
	G.arcs[12][14] = G.arcs[14][12] =510;
	G.arcs[13][15] = G.arcs[15][13] =260;
	for (i = 0; i < 16; i++)
	{
		for (j = 0; j < 16; j++)
		{
			if (i != j && G.arcs[i][j] == 0)
			{
				G.arcs[i][j] = INFINTY;
			}
		}

	}
	for (i = 0; i <16; i++)
	{
		G.vexs[i].number = i;
	}
    G.arcnum = 27;
}

 之后我们来看相关的菜单:

void printsystem()
{
	cout << endl;
	cout << "       安徽大学欢迎您!      \n";
	cout << "             AHU             \n";
	cout << "*****************************\n";
	cout << "*   欢迎来到景点查询系统    *\n";
	cout << "*      1.查看所有景点       *\n";
	cout << "*      2.景点查询           *\n";
	cout << "*      3.问路查询           *\n";
	cout << "*      4.高级功能           *\n";
	cout << "*      0.退出程序           *\n";
	cout << "*****************************\n";
	cout << endl;
}

主函数实现相关功能:

其中的高级功能中还二层嵌套着一个菜单:

int main()
{
	int x = 10;
    MGraph G;
    CreateGraph(G);
	printsystem();
	while (x != 0)
	{
		cin >> x;
		while (x != 1 && x != 2 && x != 3 && x != 4&& x!= 0)
		{
			cout << "错误,请重新输入:" << endl;
			cin >> x;
		}
		switch (x)
		{
		case 1:Allprint(G); cout << endl; break;
        case 2:FindGraph(G); break;
		case 3:
		{
			int qidian;//起点
			int zhongdian;
			int p[v] = { 0 };//p数组为path
			int D[v] = { 0 };//D数组为最短距离
			cout << "请输入起点的编号:\n";
			cin >> qidian;
			cout << "请输入目的地:\n";
			cin >> zhongdian;
			Dijkstra(G, qidian, p, D);
			shortpath(G,p, D, qidian,zhongdian);
			break;
		}
		case 4:
		{
			cout << "    请输入你想要的相关操作:     " << endl;
			cout << "********************************\n";
			cout << "    1.修改已有景点的相关信息    \n";
			cout << "  2.增加一个新景点及其相关信息  \n";
			cout << "      3. 增加一条新的路径       \n";
			cout << "  4. 删除一个景点及其相关信息   \n";
			cout << "       5. 删除一条路径          \n";
			cout << "********************************\n";
			int z;
			cin >> z;
			switch (z)
			{
			case 1:changeinfo(G); break;
			case 2:addves(G); break;
			case 3:addarc(G); break;
			case 4:del_ves(G); break;
			case 5:del_arcone(G); break;
			default:cout << "输入数据错误!\n"; break;
			}
		}break;
        case 0:x = 0; break;
		}
		printsystem();
		cout << endl << endl;
	}
	cout << "谢谢您的使用,欢迎您再来安大!" << endl;
	cout << "       AHU永远欢迎您!" << endl;
	return 0;
}

所有准备工作做好了,我们可以来到正题部分:

首先给出迪杰斯特拉算法,这部分基本和书上一样

void Dijkstra(MGraph G, int v0, int p[], int D[])
{
	int judge[v];//判断v在不在当前集合中
	for (int i = 0; i < G.vexnum; i++)
	{
		judge[i] = 0;
		D[i] = G.arcs[v0][i];//初始化每个点到v0的路径长度
		p[i] = 0;
	}
	D[v0] = 0;//自己到自己的最短路径为0
	judge[v0] = 1;//把v0放入集合之中
	int k = 0;
	for (int i = 0; i < G.vexnum; i++)
	{
		int min = INFINTY;
		for (int w = 0; w < G.vexnum; w++)
		{
			if (!judge[w])//w不在集合中
			{
				if (D[w] < min)
				{
					k = w;
					min = D[w];
				}
			}
		}
		judge[k] = 1;
		for (int w = 0; w < G.vexnum; w++)
		{
			if (!judge[w] && (min + G.arcs[k][w] < D[w]))
			{
				D[w] = min + G.arcs[k][w];//最短路径长度
				p[w] = k;//记录点
			}
		}
	}
}

最短路径的实现(核心为建立临时数组):

void shortpath(MGraph G,int p[], int D[], int y, int x)
{
	int temp[20] = { 0 }; int j = 0; int x0 = x;//x0储存终点
	while (p[x] != 0)//当p[x]非零时用temp数组储存前驱
	{
		temp[j] = p[x];
		x = p[x];
		j++;
	}
	j--;//指针退一位
	cout << "路径为:" << endl;
	cout << G.vexs[y].name;//输出起点
	for (; j >=0; j--)//输出路径
	{
		cout << "->" << G.vexs[temp[j]].name;
	}
	cout << "->" << G.vexs[x0].name;//输出终点
	cout << endl;
	if (D[x0] == 10000) { cout << "不存在路径!" << endl; return; }
	cout << "最短距离为:" << D[x0] << endl;
}

接下来看看菜单中的高级选项:

(1)修改景点信息

void changeinfo(MGraph& G)//修改景点信息
{
	int x;
	cout << "请输入你想要修改的编号:" << endl;
	cin >> x;
	if (x >= G.vexnum || x < 0) { cout << "错误!" << endl; return; }//输入的x不合法
	cout << "修改名称:" << endl;
	cin >> G.vexs[x].name;
	cout << "修改相关信息:" << endl;
	cin >> G.vexs[x].info;
	cout << "成功!" << endl;
}

(2)增添一个新顶点

void addves(MGraph& G)
{
	if (G.vexnum == v) 
	{
		cout << "景点已满!" << endl; return;
	}
	cout << "请输入你想要增添的景点:" << endl;
	cin >> G.vexs[G.vexnum].name;
	cout << "请输入你想要增添的相关景点的信息:" << endl;
	cin >> G.vexs[G.vexnum].info;
	G.vexs[G.vexnum].number = G.vexnum;
	for (int i = 0; i < G.vexnum; i++)
	{
		G.arcs[i][G.vexnum] = G.arcs[G.vexnum][i] = INFINTY;//目前这个点和别的点距离无限大
	}
	G.arcs[G.vexnum][G.vexnum] = 0;
	G.vexnum++;
	cout << "处理成功!" << endl;
}

(3)增添一条新边

void addarc(MGraph& G)
{
	int x, y; int z;
	cout << "请输入你想要增添的边相连着哪两个景点(空格分隔两个数):" << endl;
	cin >> x; if (x >= G.vexnum || x < 0) { cout << "错误!" << endl; return; }//输入的x不合法
	cin >> y; if (y >= G.vexnum || y < 0) { cout << "错误!" << endl; return; }//输入的y不合法
	cout << "请输入此边的权值:" << endl;
	cin >> z;
	G.arcs[x][y] = G.arcs[y][x] = z;
	G.arcnum++;
	cout << "处理成功!" << endl;
}

(4)删除一个顶点(这里感觉写得不太好)

void del_ves(MGraph& G)
{
	int x; int sum = 0;//sum统计一共清除了多少条边
	cout << "输入你想要删除的顶点的编号:" << endl;
	cin >> x;
	if (x >= G.vexnum || x < 0) { cout << "错误!" << endl; return; }//输入的x不合法
	strcpy(G.vexs[x].info, "空");
	strcpy(G.vexs[x].name, "空");//将顶点信息为空
	for (int w = 0; w < G.vexnum; w++)//清空关于x的边
	{
		G.arcs[w][x] = INFINTY;
		G.arcs[x][w] = INFINTY;
		sum++;
	}
	G.vexnum--;
	G.arcnum = G.arcnum - sum;
	cout << "处理成功" << endl;
}

(5)删除一条边

void del_arcone(MGraph& G)
{
	int x; int y;
	cout << "请输入你想要删除哪两个景点之间的路径(用编号表示,用空格隔开):" << endl;
	cin >> x; if (x >= G.vexnum || x < 0){cout << "数据有误!" << endl; return;}
	cin >> y; if (y >= G.vexnum || y < 0){cout << "数据有误!" << endl; return;}
	G.arcs[x][y] = G.arcs[y][x] = INFINTY;
	cout << "处理成功!" << endl;
}

以上就是本导游系统的所有代码部分了

接下来看看部分运行的图片(只展示部分):

 

d39e7cb1a43e4e2bbce311de7565fca4.png

 

5a97899cd6b74e5595e9f1f52c5d4274.png

 接下来我们试一下最短路径:

(1)从体育馆到南体育场

da0b4c2de22a435594e560bee050251a.png

 aa5f62c5e13f4f289b2a075ccc51f901.png

(2) 从杏园宿舍到文典阁

 65573b470dba4d258628624ae069c1cc.png

 a527cd2b8b354ef29fe65a093668001c.png

 (3)从橘园食堂到孔子像

72dcd5bb7e6142b89658f6519430d80e.png

183a71768b4340cab6f2060500edff7e.png

 以上就是本次的全部内容了。

代码仅供参考,请勿直接抄袭!请勿转载!仅供交流学习使用!谢谢~

 

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值