校园导游程序–基于链式前向星

校园导游程序–基于链式前向星

一、课题内容分析

用无向网表示你所在学校的校园景点平面图,图中顶点表示主要景点,存放景点的编号、名称、简介等信息,图中的边表示景点间的道路,存放路径长度等信息。要求能够回答有关景点介绍、游览路径等问题。

1、查询各景点的相关信息。

2、查询图中任意两个景点间的最短路径。

3、查询图中任意两个景点间的所有路径。

4、增加、删除、更新有关景点和道路的信息。

二、需求分析

(1) 所需知识点

1、 图的各种遍历算法

2、单源最短路径(Dijkstra算法)

3、图的储存结构(链式前向星)

4、文件的读取存储操作

5、界面交互

(2)、数据结构

本课题用到的数据结构是图的数据结构,其中用到的是链式前向星作为储存结构

typedef struct Edge {

     int to;           //到达点

     int w;            //边权值

     int next;         //当前起点的下一条边的起始edge的号

  }Edge;

  
  int head[maxn]; 

  //顶点,边数
  int v, e;

3、基本算法的实现

searchLocation(); //查询景点信息

shortPath(); //打印两点最短路径

dfsAllPath(); //遍历两点间的所有路径

addNode(); //增加景点

deleteNode(); //删除景点

updateNode(); //更新道路信息,景点信息

systemExit(&quit); //退出系统

printMap(); //打印校园地图

三、开发人员

独立开发

四、开发平台

VSCode

五、代码内容

part 1 数据结构,结点储存,全局变量准备

//景点信息储存
typedef struct Node
{
    int num;
    char name[20];
    char intro[1000];
}Node;

//链式前向星,本质邻接表
typedef struct Edge {
    int to;           //到达点
    int w;            //边权值
    int next;         //当前起点的下一条边的起始edge的序号
}Edge;

//初始化常量
const int maxn = 100;
const int INF = 0X3f3f3f3f;

//顶点,边数
int v, e; 
//头准备
int head[maxn]; 
//全局变量准备
int visted[maxn];     
int parent[maxn];   
int dist[maxn]; 
int cnt;        
Edge edge[maxn];
Node node[maxn];
int sta[maxn];
int top;
int countRoads;

typedef pair<int, int> iPair; 

part 2 文件读入,全局变量初始化,读入边信息

//初始化全局变量
void InitVa(){
    memset(sta,-1,sizeof(sta));
    memset(parent,-1,sizeof(parent));
    memset(dist, INF, sizeof(dist));
    memset(visted,0,sizeof(visted));
    top = -1;
    countRoads = 0;
}
//初始化
void init() { 
        InitVa();
        cnt = 0;
        memset(head, -1, sizeof(head));       //head初始化后不会发生变化
        ifstream myfile("map2.txt"); 
        if(myfile.is_open()){
		      myfile >> v >> e;
          for(int i = 0; i < v; i++){
		      myfile >> node[i].num >> node[i].name >> node[i].intro;
        }
	        for(int k = 0; k < e; k++){	
              int from, to, next;
              myfile >> from >> to >> next;
	      	    adde(from,to,next);
      }
          myfile.close();   
    }
	    else{
            cout << "没有地图信息!";
      }
}

part 3 主菜单,景点图显示

注:本程序是基于本学校的位置图

// 主菜单
int menu() {
	int s;
	printf("\t\t                ┌───────────────────┐                \n");
	printf("\t\t┌──────├── 欢迎使用校园导游系统 ──┤──────┐\n");
	printf("\t\t│              └───────────────────┘              │\n");
	printf("\t\t│                                                                               │\n");
	printf("\t\t│                                                                      │\n");
	printf("\t\t│   ┌────────────┐        ┌────────────┐   │\n");
	printf("\t\t│   1.景点信息查询       2.两景点间最短路径查询   │\n");
	printf("\t\t│   └────────────┘        └────────────┘   │\n");
	printf("\t\t│                                                                      │\n");
	printf("\t\t│   ┌────────────┐        ┌────────────┐   │\n");
	printf("\t\t│   3.两景点间所有路径查询   4.增加景点信息    │\n");
	printf("\t\t│   └────────────┘        └────────────┘   │\n");
	printf("\t\t│                                                                      │\n");
	printf("\t\t│   ┌────────────┐        ┌────────────┐   │\n");
	printf("\t\t│   │ 5.删除景点信息         6.更改景点信息    │\n");
	printf("\t\t│   └────────────┘        └────────────┘   │\n");
  printf("\t\t│   ┌────────────┐        ┌────────────┐   │\n");
	printf("\t\t│             7.退出校园导游系统    │\n");
	printf("\t\t│   └────────────┘        └────────────┘   │\n");
	printf("\t\t│                                                                      │\n");
	printf("\t\t└───────────────────────────────────┘\n\n");
	printf("\t\t请根据你的需求选择操作:");
	scanf("%d", &s);
	printf("\n\n");
	return s;
}
// 校园景点图的显示
void printMap() {
	printf("\n                                           『校园地图』\n\n\n\n");
	printf("                                         ===◎(5)运动场===                            \n");
	printf("	                                  		                   ===◎(7)第一教学楼===                       \n");
	printf("	                  ===◎(4)图书馆===               \n");
	printf("	                                                ===◎(6)第二教学楼===                \n");
	printf("	                                                                            		===◎(8)篮球场===\n");
	printf("	                                                     		\n");
	printf("	            ===◎(3)会堂===                                               ===◎游泳馆(9)=== \n");
	printf("	                                                             \n");
	printf("	                           ===◎(2)校历史展览馆===		                                            \n");
	printf("	                                                     		\n");
	printf("           ===◎(1)西 门===                                                                              \n");
	printf("                    			  ===◎(10)学院超市===                                                \n\n");
}

part 4 景点信息查询

// 查找景点信息
int judgeInput(int num){
  if(num > v || num < 0 || node[num-1].num == -1){
        return 0;
  }
    return 1;
}
void searchLocation() {
	int s;
  cout << "请输入你要查找的景点编号:";
	cin >> s;
  cout << endl;

  while(judgeInput(s)){
    
    cout << "景点名称 :" << node[s-1].name << endl << endl;
	cout << "景点简介 :" << node[s-1].intro << endl << endl;

    cout << "请输入你要查找的景点编号:";
	cin >> s;
    cout << endl;
  }
    cout << "景点不存在,或者景点已被移除" << endl;
}

part 5 两点间最短路径

//两点间的最短路径
void dijkstra(int from){
     
        //优先队列准备
        priority_queue< iPair, vector <iPair> , greater<iPair> > pq;

       //距离,头
        pq.push(make_pair(0,from));
        dist[from] = 0;

        parent[from] = -1;
 
        while(!pq.empty()){
          
            from = pq.top().second;
            visted[from] = 1;
            pq.pop(); 
            for(int i = head[from]; ~i; i = edge[i].next){

              if(!visted[edge[i].to]){
             
              int v = edge[i].to;
              int weight = edge[i].w;

              if(dist[v] > dist[from] + weight){
                
                parent[v] = from;
                dist[v] = dist[from] + weight;
                pq.push(make_pair(dist[v], v));
              }
            }   
        }
      }
}

//打印两点的最短路径
  void shortPath(){
        InitVa();
        int from, to;
        cout << "请输入from->to,景点编号: " << endl;
  
        cin >> from >> to;
        if(!judgeInput(from) || !judgeInput(to)){
                cout << "景点编号输入错误~" << endl;
                return;
        }
        --from;
        --to;
        dijkstra(from);
        
        for(int i = to; ~i; i = parent[i]){
          if(i == from){
            sta[++top] = i; //
            cout << "从" << node[from].name << "到" << node[to].name << "的最短路径如下" << endl << endl;
            for(int i = top; i >= 0; i--){
              cout << node[sta[i]].num << " " << node[sta[i]].name  << "->";
            }
            cout << "最短距离是:" << dist[to] << endl;
              return;
          };
            sta[++top] = i;       
        }
        cout << "抱歉,这期间没有路径" << endl;
  }

part 6 两点之间所有路径

void DFS(int from, int to){ 
        int i = head[from];
        visted[from] = 1;
        sta[++top] = from;
        if(from == to){
          cout <<"这是第" << ++countRoads << "条路径 :";
          for(int i = 0; i <= top; i++){
              cout << node[sta[i]].name << " -> ";
          }
          cout << endl << endl;
          top--;
          visted[to] = 0;
          return;
        }
        for( ; ~i; i = edge[i].next){
            if(!visted[edge[i].to]){
              DFS(edge[i].to,to);
            }
        } 
        if(i == -1) {
          top--;
          visted[from] = 0;
        }   
}


void dfsAllPath(){
      InitVa();
      int from, to;
        cout << "请输入from->to,景点编号: " << endl;
  
        cin >> from >> to;
        if(!judgeInput(from) || !judgeInput(to)){
                cout << "景点编号输入错误~";
                return;
        }
        --from;
        --to;
      DFS(from,to);
}

part 7 增加结点,增加边

void addNode(){
      int from,to,w;
      cout << "请输入景点编号, 景点名字, 景点介绍";
      cin >> node[v].num >> node[v].name >> node[v].intro;
      ++v;
      cout << "请输入要增加的边: from->to, weight" << endl;
      cin >> from >> to >> w;
      --from;
      --to;
      adde(from,to,w);
}

part 8 删除结点,删除边

void deleteedge(int from, int to){
      for(int i = head[from];~i ; i = edge[i].next){
            if(edge[head[from]].to == to){
            head[from] = edge[head[from]].next;
            break;
      }
            if(edge[edge[i].next].to == to){
                edge[i].next = edge[edge[i].next].next;
                break;
            }
      }
      for(int i = head[to]; ~i ; i = edge[i].next){
            if(edge[head[to]].to == from){
              head[to] = edge[head[to]].next;
              break;
            }
            if(edge[edge[i].next].to == from){
                edge[i].next = edge[edge[i].next].next;
                break;
            }
      }

}

void deleteNode(){
      int num;
      cout << "请输入要删除的景点编号";
      cin >> num;

      node[num-1].num = -1; //judge
      for(int i = head[num-1];~i; i = edge[i].next){
          deleteedge(num-1,edge[i].to);
      }
      head[num - 1] = -1;
}

part 8 更新结点信息,道路信息

bool isUpdateName(){
    cout << "是否更改景点名称: " << endl;
    bool j;
    
    cout << "Yes: 1, No: 0" << endl;
    cin >> j;
    return j;
}

bool isUpdateIntro(){
    cout << "是否更改景点介绍: " << endl;
    bool j;
    cout << "Yes: 1, No: 0" << endl;
    cin >> j;
    return j;
}

bool isAddWay(int *from, int *to, int *w){
    cout << "是否增加道路信息: " << endl;
    bool j;
    cout << "Yes: 1, No: 0" << endl;
    cin >> j;
    if(j){
    cout << "请输入道路信息 from -> to, weight" << endl;
    cin >> *from >> *to >> *w;
    }
    return j;
}

bool isDeleteway(int *from, int *to){
    cout << "是否删除道路信息: " << endl;
    bool j;
    cout << "Yes: 1, No: 0" << endl;
    cin >> j;
    if(j){
    cout << "请输入道路信息 from -> to" << endl;
    cin >> *from >> *to;
    }
    return j;

}



void updateNode(){
     int num;
     int i, j, k;
     char name[20];
     char intro[1000];
      cout << "请输入要更新的景点编号" << endl;
      cin >> num;
      if(isUpdateName()){
        cin >> name;
        strcpy(node[num-1].name,name);
      }
      if(isUpdateIntro()){
        cin >> intro;
       strcpy(node[num-1].intro,intro);
      }
      if(isAddWay(&i, &j, &k)){
            adde(i-1,j-1,k);
         }
      if(isDeleteway(&i,&j)){
            deleteedge(i-1,j-1);
      }   
}

part 9 退出系统

void systemExit(int *quit) {
	*quit = 1;
	printf("\t\t欢迎使用,期待下次光临\n\n");
}

part 10 主函数

int main(){
    init();
	  int quit = 0;                                                                                                                  
		while (!quit) {                                                         
			switch (menu()) {                                                   
			case 1:system("cls"); printMap(); searchLocation(); break;         
			case 2:system("cls"); printMap(); shortPath(); break;        
			case 3:system("cls"); printMap(); dfsAllPath(); break;          
			case 4:system("cls"); printMap(); addNode(); break;  
			case 5:system("cls"); printMap(); deleteNode(); break; 
            case 6:system("cls"); printMap(); updateNode(); break; 
			case 7:system("cls"); printMap(); systemExit(&quit); break; 
			default:printf("\t\t\t\t\t错误!没有该选项对应的操作。\n\n");
		}
			system("pause");
			system("cls");                                                           /*清屏*/
	}
	    system("pause");
}

这是我在CSDN上的第一篇博客,喜欢的小伙伴期待你的赞哦,另外也欢迎各位大佬调试,若有问题,请留言告知。如果有疑问的朋友,也可以留言哦。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值