數據結構課程設計——校園導游系統
主要的任務為兩個:
- 求兩點間最短路徑。(迪傑斯特拉算法)
- 求兩點間簡單路徑。(dfs)
難度不大。部分有注釋。
//先是MGraph中的主要算法實現
#ifndef MGRAPH_H_INCLUDED
#define MGRAPH_H_INCLUDED
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
#define MAX_VEX 20
#define MAX_NUM 32767
typedef struct vex
{
string name;
string info;
} vex, *vexptr;
//圖的鄰接矩陣存儲表示
typedef struct
{
vex vexs[MAX_VEX]; //頂點表
int arcs[MAX_VEX][MAX_VEX]; //鄰接矩陣
int vexnum, arcnum; //圖的當前點數和邊數
} MGraph;
//獲取頂點位置:若G中存在頂點u,則返回該頂點在圖中的位置;否則返回其他信息
int LocateVex(MGraph &G, string u)
{
int index = -1; //原始下標,沒找到元素返回-1
for(int i = 0; i < G.vexnum; i++) //遍歷頂點數組
{
if(u == G.vexs[i].name)
{
index = i; //記錄元素下標
}
}
return index; //返回下標
}
void MapOfHdu()
{
cout<<"==============簡略地圖(地點括號內為在頂點表中的下標)============="<<endl;
cout<<"八號樓(8)"<<endl;
cout<<" 學生活動中心(10) "<<endl;
cout<<" 圖書館(9)"<<endl;
cout<<""<<endl;
cout<<" 體育館(5)"<<endl;
cout<<""<<endl;
cout<<" 六號樓(6) 七號樓(7) "<<endl;
cout<<""<<endl;
cout<<" 四號樓(4)"<<endl;
cout<<" 三號樓(3)"<<endl;
cout<<" 二號樓(2)"<<endl;
cout<<" 一號樓(1)"<<endl;
cout<<"============================南大門(0)============================"<<endl;
}
int CreateMap(MGraph &G)
{
G.vexnum = 11;//頂點數
G.arcnum = 17;//邊數
//初始化鄰接矩陣,所有邊的權值置INF(MAX_NUM)
for(int i = 0; i < G.vexnum; ++i)
{
for(int j = 0; j < G.vexnum; ++j)
{
G.arcs[i][j] = MAX_NUM;
}
}
G.vexs[0].name = "南大門";
G.vexs[0].info = "南大門為學校正大門";
G.vexs[1].name = "一號樓";
G.vexs[1].info = "信仁樓";
G.vexs[2].name = "二號樓";
G.vexs[2].info = "信義樓";
G.vexs[3].name = "三號樓";
G.vexs[3].info = "信禮樓";
G.vexs[4].name = "四號樓";
G.vexs[4].info = "在建";
G.vexs[5].name = "體育館";
G.vexs[5].info = "體育館簡介";
G.vexs[6].name = "六號樓";
G.vexs[6].info = "信誠樓";
G.vexs[7].name = "七號樓";
G.vexs[7].info = "信博樓";
G.vexs[8].name = "八號樓";
G.vexs[8].info = "信遠樓";
G.vexs[9].name = "圖書館";
G.vexs[9].info = "圖書館簡介";
G.vexs[10].name = "學生活動中心";
G.vexs[10].info = "學生活動中心簡介";
//初始化各邊權值
G.arcs[0][1] = 100;
G.arcs[0][2] = 100;
G.arcs[0][3] = 300;
G.arcs[1][2] = 250;
G.arcs[1][3] = 100;
G.arcs[2][3] = 250;
G.arcs[3][4] = 350;
G.arcs[3][8] = 1000;
G.arcs[4][5] = 500;
G.arcs[4][6] = 300;
G.arcs[4][8] = 800;
G.arcs[5][6] = 200;
G.arcs[5][10] = 900;
G.arcs[7][8] = 850;
G.arcs[7][9] = 150;
G.arcs[7][10] = 250;
G.arcs[9][10] = 150;
G.arcs[1][0] = 100;
G.arcs[2][0] = 100;
G.arcs[3][0] = 300;
G.arcs[2][1] = 250;
G.arcs[3][1] = 100;
G.arcs[3][2] = 250;
G.arcs[4][3] = 350;
G.arcs[8][3] = 1000;
G.arcs[5][4] = 500;
G.arcs[6][4] = 300;
G.arcs[8][4] = 800;
G.arcs[6][5] = 200;
G.arcs[10][5] = 900;
G.arcs[8][7] = 850;
G.arcs[9][7] = 150;
G.arcs[10][7] = 250;
G.arcs[10][9] = 150;
return 1;
}
//景點介紹
int GetInfo(MGraph &G, string u)
{
for(int i = 0; i < G.vexnum; i++)
{
if(G.vexs[i].name == u)
{
cout<<"有關該景點的信息是:";
cout<< G.vexs[i].info << endl;
return 1;
}
}
cout << "未查詢到此景點!" << endl;
return 0;
}
int GetDistance(MGraph &G, string u1,string u2)
{
int id1,id2;
id1=LocateVex(G,u1);
id2=LocateVex(G,u2);
return G.arcs[id1][id2]<MAX_NUM?G.arcs[id1][id2]:-1;
}
void Dijkstra(MGraph G,int v,int dist[],int path[])
{
int Set[MAX_VEX];
int Min,u;
//對數組進行初始化//
for(int i=0; i<G.vexnum; i++)
{
dist[i]=G.arcs[v][i];
Set[i]=0;
if(G.arcs[v][i]<MAX_NUM)
{
path[i]=v;
}
else
{
path[i]=-1;
}
Set[v]=1;
path[v]=-1;
}
//關鍵操作//
for(int i=0; i<G.arcnum-1; i++)
{
Min=MAX_NUM;
//循環每次從剩余頂點中挑出一個頂點,它是S集通往所有頂點的路徑長度最小的那個//
for(int j=0; j<G.arcnum; j++)
{
if(Set[j]==0&&dist[j]<Min)
{
u=j;
Min=dist[j];
}
}
Set[u]=1;//將選出的頂點並入最短路徑中
//循環以剛並入的頂點對通往剩余頂點的所有路徑進行檢測//
for(int j=0; j<G.arcnum; j++)
{
//if判斷頂點U的加入是否會出現通往頂點j的更短的路徑,如果出現,則改變原來路徑及其長度,否則不變//
if(Set[j]==0&&dist[u]+G.arcs[u][j]<dist[j])
{
dist[j]=dist[u]+G.arcs[u][j];
path[j]=u;
}
}
}
//算法結束后,dist[]中存放初始頂點v到其余頂點的最短路徑長度,path[]中存放v到其余頂點的最短路徑//
}
void printPath(int path[],int a)
{
//path實際上是一顆雙親存儲結構的樹,故需要棧來將其逆序輸出//
int Stack[MAX_VEX];
int top=-1;
while(path[a]!=-1)
{
Stack[++top]=a;
a=path[a];
}
Stack[++top]=a;
while(top!=-1)
{
cout<<Stack[top--]<<" ";
}
cout<<endl;
}
int visited[MAX_VEX]= {0};
int DFSpath[MAX_VEX]= {0};
int DFStop=-1;
void DFS(MGraph & G,int v,int e)
{
visited[v]=1;
DFSpath[++DFStop]=v;
for(int i=0; i<G.vexnum; i++)
{
if(v==e)
{
for(int j=0; j<=DFStop; j++)
{
cout<<DFSpath[j]<<" ";
}
cout<<endl;
visited[v]=0;
DFStop--;
break;
}
if((G.arcs[v][i]<MAX_NUM)&&(!visited[i]))
{
DFS(G,i,e);
}
if(i==G.vexnum-1)//准備回溯前先處理棧和當前節點狀態
{
DFStop--;
visited[v]=0;
}
}
}
#endif // MGRAPH_H_INCLUDED
之后是主程序實現。
#include <iostream>
#include "MGraph.h"
using namespace std;
void menu()
{
cout << "----------------------歡迎咨詢校園導游系統---------------------- "<< endl;
cout << "--------------------請在屏幕上輸入相應的數字--------------------- "<< endl;
cout << " 【1】. 查看地圖 " << endl;
cout << " 【2】. 信息查詢 " << endl;
cout << " 【3】. 最短路徑查詢 " << endl;
cout << " 【4】. 簡單路徑查詢 " << endl;
cout << " 【5】. 退出程序 " << endl;
cout<< "-------------------------------------------------------------------" << endl;
}
int main(){
MGraph G;
int m;
string b;
CreateMap(G);
while(1){
menu();
cin>> m;
switch(m){
case 1:
{
MapOfHdu();
system("pause");
system("cls");
break;
}
case 2:
{
MapOfHdu();
cout << "請輸入要查詢的位置名稱:";
cin>> b;
GetInfo(G, b);
system("pause");
system("cls");
break;
}
case 3:
{
MapOfHdu();
string v1, v2;
int v1i,v2i;
int dist[MAX_VEX],path[MAX_VEX];
cout << "請輸入起點和終點:(輸入名稱並以空格間隔)";
cin>> v1 >> v2;
cout << v1 << "到" << v2 << "的最短路徑長為:";
v1i=LocateVex(G,v1);
v2i=LocateVex(G,v2);
Dijkstra(G,v1i,dist,path);
cout<<dist[v2i]<<endl;
cout << v1 << "到" << v2 << "的最短路徑為:";
printPath(path,v2i);
cout<< endl;
system("pause");
system("cls");
break;
}
case 4:
{
MapOfHdu();
string v1, v2;
int v1i,v2i;
cout << "請輸入起點和終點:(輸入名稱並以空格間隔)";
cin>> v1 >> v2;
cout << v1 << "到" << v2 << "的所有簡單路徑為:"<<endl;
v1i=LocateVex(G,v1);
v2i=LocateVex(G,v2);
DFS(G,v1i,v2i);
system("pause");
system("cls");
break;
}
case 5:
return 0;
}
}
}