您的位置:首页 > 理论基础 > 数据结构算法

用无向带权图实现校园导航系统

2015-04-16 22:42 260 查看
学校数据结构的课程实验之一。

用到的数据结构:无向带权图

用到的算法:Floyd最短路径算法,深度优先搜索(递归实现)

需求分析:

  设计一个校园导航程序,为访客提供各种信息查询服务:

1. 以图中各顶点表示校内各单位地点,存放单位名称,代号,简介等信息;以边表示路径,存放路径长度等相关信息。

2. 图中任意单位地点相关信息的查询。

3. 图中任意单位的问路查询,即查询任意两个单位之间的一条最短的路径。

4. 从图中任意单位地点出发的一条深度优先遍历路径。

主函数:

#include <iostream>
#include "School.h"
using namespace std;

int main()
{
School mySchool=School("School.txt");
char choice='y';
while(choice=='y')
{
cout << "请选择操作"<<endl;
cout << "--------------------------------" << endl;
cout << "1----查看地点列表" << endl;
cout << "2----查看地点简介" << endl;
cout << "3----查询最短路径" << endl;
cout << "4----从一点出发遍历" << endl;
cout << "5----任意一点的可直达地点" << endl;
cout << "--------------------------------" << endl;
int option;
cin >> option;
switch (option)
{
case 1: mySchool.display(); break;
case 2: mySchool.search(); break;
case 3: mySchool.path(); break;
case 4: mySchool.traverse(); break;
case 5: mySchool.reachable(); break;
}
cout << "继续吗?[y/n]";
cin >> choice;
}
return 0;
}


学校类:

#include <fstream>
#include <string>
#include "Digraph.h"
using namespace std;

struct Place//地点定义
{
int number;
string name;
string introduction;

Place(){}
Place(int num,string nam,string intro):number(num),name(nam),introduction(intro){}
void print()//显示此地点的信息
{
cout<<"---------------------------"<<endl;
cout<<"编号:"<<number<<endl;
cout<<"地点名:"<<name<<endl;
cout<<"简介:"<<introduction<<endl;
cout<<"---------------------------"<<endl;
}
};
ostream& operator<<(ostream &os, Place &aPlace)//重载输出运算符
{
os << aPlace.number << ":" << aPlace.name;
return os;
}
ofstream outFile;//输出流

class School
{
private:
int total;//总的地点数
Digraph<Place,13> places_graph;
void readFile(const char filename[20])//读文件
{
total = 0;
ifstream inFile;
inFile.open(filename);
char trying;
while(inFile.is_open() && !inFile.eof())
{
//先试探是否为结束符
inFile >> trying;
if (trying == '#') break;
else
{
inFile.putback(trying);
int number;
inFile>>number;
string name;
inFile>>name;
string introduction;
inFile>>introduction;
Place aPlace=Place(number,name,introduction);
//aPlace.print();//显示这个地点的信息
places_graph.insert(aPlace);
total++;
}
}
for (int i = 0; i < 13; i++)//读入距离内容
for (int j = 0; j < 13; j++)
{
int dis;
inFile >> dis;
places_graph.distance_set(i, j, dis);
}
inFile.close();
places_graph.calculate_path();//计算所有最短路径并存入数组
cout << "学校共有" << total << "个地方"<<endl;
}
static void readPlace(Place &aPlace)
{
outFile<<aPlace.number<<endl;
outFile<<aPlace.name<<endl;
outFile<<aPlace.introduction<<endl;
}
static void print(Place &aPlace)//显示此地点的信息编号、名称
{
cout<<aPlace.number<<": "<<aPlace.name<<endl;
}
static void visit(Place &aPlace)
{
cout << "->" << aPlace.number << ":" << aPlace.name << endl;
}
public:
School(const char filename[20])
{
readFile(filename);
}
void display()
{
cout<<"以下为学校的所有地点:"<<endl;
places_graph.traverse(print);
}
void search()
{
cout<<"请输入要查询的地点编号:";
int num;
cin>>num;
Place aPlace;
places_graph.search_vertex(num,aPlace);//查到要查的地点
cout<<"以下是这一地点的信息:"<<endl;
aPlace.print();
}
void path()
{
cout << "请输入想查询最短路径的两个地点的编号(如:5 7):";
int i, j;
cin >> i >> j;
places_graph.shortest_path(i, j);
}
void traverse()//深度优先遍历,输出路线
{
cout << "请输入源点的编号:";
int v;
cin >> v;
int distance;
distance = places_graph.BFS(v, visit);
cout << endl << "路径总长为:" << distance<<endl;
}
void reachable()
{
cout << "请输入源点的编号:";
int v;
cin >> v;
cout << "和地点" << v << "有直达路径的地点如下:" << endl;
places_graph.connected(v);
}
};


主程序流程图:



运行截图:











图类(邻接矩阵存储,因有向图是无向图的超集,所以可以定义为有向图,邻接矩阵为对称阵)

#include <fstream>
#include <string>

template <class Vertex,int graph_size>
class Digraph
{
public:
Digraph()
{
count=0;
for (int i = 0; i < graph_size; i++)
adjacency[i][i] = 0;
}
void insert(Vertex &new_entry)
{
nodes[count++]=new_entry;
}
void distance_set(int i, int j, int dis)
{
adjacency[i][j] = adjacency[j][i] = dis;
}
void traverse(void (*visit)(Vertex &))//遍历整个图(逐个访问各结点)
{
for(int i=0;i<graph_size;i++)
(*visit)(nodes[i]);
}
void search_vertex(int num,Vertex &target)
{
target=nodes[num];
}
void calculate_path()//计算最短路径并将结果更新到以上两个二维数组里
{
for (int i = 0; i < graph_size; i++)
{
for (int j = 0; j < graph_size; j++)
{//初始化路径长度数组,结点跟踪数组
shortest_dis[i][j] = adjacency[i][j];
trace_node[i][j] = j;
}
}
cout << "这是邻接矩阵:" << endl;
for (int i = 0; i < graph_size; i++)
{
for (int j = 0; j < graph_size; j++)
cout << adjacency[i][j] << " ";
cout << endl;
}
//Floyd算法计算任意两点之间的最短路径
for (int k = 0; k < graph_size; k++)
for (int v = 0; v < graph_size; v++)
for (int w = 0; w < graph_size; w++)
if (shortest_dis[v][k] + shortest_dis[k][w] < shortest_dis[v][w])
{
shortest_dis[v][w] = shortest_dis[v][k] + shortest_dis[k][w];
trace_node[v][w] = trace_node[v][k];
}
cout << "这是最短路径数组:" << endl;
for (int i = 0; i < graph_size; i++)
{
for (int j = 0; j < graph_size; j++)
cout << shortest_dis[i][j] << " ";
cout << endl;
}
cout << "这是结点跟踪数组:" << endl;
for (int i = 0; i < graph_size; i++)
{
for (int j = 0; j < graph_size; j++)
cout << trace_node[i][j] << " ";
cout << endl;
}
}
void shortest_path(int i, int j)
{
cout << "从" << i << "到" << j << "的最短路径长度为" << shortest_dis[i][j] << endl;
cout << "路径为:" << endl;
int k = trace_node[i][j];
cout << i ;
while (k != j)
{
cout << "->" << k;
k = trace_node[k][j];//从起点出发,找到途经结点
}
cout << "->" << j << endl;
}
void connected(int v)//输出所有和v直达的结点
{
for (int i = 0; i < graph_size; i++)
{
if (adjacency[v][i] != 100 && adjacency[v][i] != 0)
cout << nodes[i] << " 距离为:" << adjacency[v][i] << ";" << endl;
}
}
int BFS(int v,void (*visit)(Vertex &))
{
distance = 0;
bool visited[graph_size] = { false };
Vertex src = nodes[v];//找到选定的源点
visited[v] = true;
(*visit)(src);
for (int i = 0; i < graph_size; i++)
{
if (adjacency[v][i] != 100 && adjacency[v][i] != 0)//对相邻点进行深度优先遍历
traverse(i, visited, visit);
}
return distance;
}
private:
int count;//结点数
int distance;//一条遍历路径总长
int adjacency[graph_size][graph_size];//存储权的邻接矩阵
Vertex nodes[graph_size];//存储结点内容的一维数组
int shortest_dis[graph_size][graph_size];//保存最短路径长度
int trace_node[graph_size][graph_size];//保存结点跟踪路径
void traverse(int v, bool visited[], void (*visit)(Vertex &))//辅助遍历函数
{
if (visited[v] == false)
{
(*visit)(nodes[v]);
visited[v] = true;
for (int i = 0; i < graph_size; i++)
if (adjacency[v][i] != 100 && adjacency[v][i] != 0 && visited[i] == false)
{
traverse(i, visited, visit);//递归地进行深度优先遍历
distance += adjacency[v][i];
}

}
}
};


附:测试用的文件School.txt内容

前门
南门;车辆进出
教一楼
阶梯教室;英语教室
教二楼
普通教室
教三楼
实验室;办公室;阶梯教室
学一公寓
男生宿舍
学二公寓
男生宿舍
学三公寓
女生宿舍
学四公寓
男生宿舍
食堂
一层;二层;清真
水房
在食堂旁边
操场
300米一圈的跑道
图书馆
借阅部;自习室
后门
北门;取快递
#
1   4   8   6 100 100  10 100   1 100  10 100
0   3   4   5 100  10 100   1 100   1 100 100
3   0  10   1   7 100   6 100  10 100 100   8
4  10   0   2 100   3 100 100   6   5   9   7
5   1   2   0   3   6   9 100   7   9   8   5
100   7 100   3   0 100   5 100   6   7   8   4
10 100   3   6 100   0   2   7   2   9  10   2
100   6 100   9   5   2   0   4 100   2   3   7
1 100 100 100 100   7   4   0  10   4   5   1
100  10   6   7   6   2 100  10   0   8   5   7
1 100   5   9   7   9   2   4   8   0   2   9
100 100   9   8   8   10  3   5   5   2   0 100
100   8   7   5   4   2   7   1   7   9  100  0

School.txt
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构