华为机试之广度优先遍历
在华为的论坛上看到了下面这个题目,想着最近刚好没事,就来写一下。
编译环境:VS2005
高级题:地铁换乘
已知2条地铁线路,其中A为环线,B为东西向线路,线路都是双向的。经过的站点名分别如下,两条线交叉的换乘点用T1、T2表示。编写程序,任意输入两个站点名称,输出乘坐地铁最少需要经过的车站数量(含输入的起点和终点,换乘站点只计算一次)。地铁线A(环线)经过车站:A1 A2 A3 A4 A5 A6 A7 A8 A9 T1 A10 A11 A12 A13 T2 A14 A15 A16 A17 A18
地铁线A(直线)经过车站:B1 B2 B3 B4 B5 T1 B6 B7 B8 B9 B10 T2 B11 B12 B13 B14 B15
输入:输入两个不同的站名
输出:输出最少经过的站数,含输入的起点和终点,换乘站点只计算一次
刚开始看到这道题的时候,感觉是用链表,但具体怎么写不会
参考了别人的程序,具体思路是先用邻接表建立无向图,然后广度优先遍历
之前学数据结构的时候,只是明确了排序、链表、查找、图等基本概念,具体如何用程序实现则没有涉及
这里有2个基本数据结构,边表edgenode和顶点表vernode
顶点表指各链表的第一个
链表中除第一个其他是边表
左图为环线A线,右图为直线B线,其中9为换乘站T1,14为换乘站T2
广度优先遍历:
这里我们需要用到队列queue,需要include<queue>
1.指定起点A2和终点A4
2.若顶点A2不在队列中,则将顶点A2压入队列
3.将顶点A2弹出队列前,先检查该顶点A2是不是终点,若是,则break;若不是,则将该顶点A2的下一层的顶点(A3和A1)压入队列,然后把该顶点A2弹出队列。当将下一层的顶点压入队列时,计数值加1,这样我们就可以得到下一层该检查的顶点数(在此例中是2)
4.检查该层的顶点是否都检查完,若没检查完,则继续第3步;若检查完了,则开始下一层的检查
下图为简易思路:
下面给出实现代码:
#include <vector> #include <iostream> #include <conio.h> #include <string.h> #include <queue> using namespace std; #define MAX 35 #define SUBWAY_A 20 #define SUBWAY_B 15 typedef struct node{//边表 int adjvex; struct node *next; }edgenode; typedef struct{//顶点表 int data; edgenode *first; char name[5]; char visit_flag; }vernode; const char subway_name1[SUBWAY_A][5]={"A1","A2","A3","A4","A5","A6","A7","A8","A9","T1","A10","A11","A12","A13","T2","A14", "A15","A16","A17","A18"}; const char subway_name2[SUBWAY_B][5]={"B1","B2","B3","B4","B5","B6","B7","B8","B9","B10","B11","B12","B13","B14","B15"}; vernode ga[MAX]; /* 函数输入:vernode ga[]顶点表 函数输出:无 函数功能:用邻接表表示图 */ void creat(vernode ga[]) { edgenode *p; //初始化 for(int i=0;i<MAX;i++) { ga[i].first = NULL; ga[i].visit_flag = 0;//未入列 if(i<=19) strcpy(ga[i].name,subway_name1[i]); else strcpy(ga[i].name,subway_name2[i-SUBWAY_A]); } //建立A地铁图 for(int i=1;i<=SUBWAY_A-2;i++) { ga[i].data = i; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = i-1; p->next = ga[i].first; ga[i].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = i+1; p->next = ga[i].first; ga[i].first = p; } //0顶点 ga[0].data = 0; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 19; p->next = ga[0].first; ga[0].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 1; p->next = ga[0].first; ga[0].first = p; //19顶点 ga[19].data = 19; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 18; p->next = ga[19].first; ga[19].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 0; p->next = ga[19].first; ga[19].first = p; //9 T1换乘站 p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 24; p->next = ga[9].first; ga[9].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 25; p->next = ga[9].first; ga[9].first = p; //14 T2换乘站 p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 29; p->next = ga[14].first; ga[14].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 30; p->next = ga[14].first; ga[14].first = p; //建立B地铁图 for(int i=1+SUBWAY_A;i<=33;i++) { if((i==24)|(i==25)|(i==29)|(i==30))continue; ga[i].data = i; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = i-1; p->next = ga[i].first; ga[i].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = i+1; p->next = ga[i].first; ga[i].first = p; } //24顶点连接9 T1 ga[24].data = 24; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 23; p->next = ga[24].first; ga[24].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 9; p->next = ga[24].first; ga[24].first = p; //25顶点连接9 T1 ga[25].data = 25; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 26; p->next = ga[25].first; ga[25].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 9; p->next = ga[25].first; ga[25].first = p; //29顶点连接14 T2 ga[29].data = 29; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 28; p->next = ga[29].first; ga[29].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 14; p->next = ga[29].first; ga[29].first = p; //30顶点连接14 T2 ga[30].data = 30; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 31; p->next = ga[30].first; ga[30].first = p; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 14; p->next = ga[30].first; ga[30].first = p; //20端点连接21 ga[20].data = 20; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 21; p->next = ga[20].first; ga[20].first = p; //34端点连接33 ga[34].data = 34; p = (edgenode*)malloc(sizeof(edgenode)); p->adjvex = 33; p->next = ga[34].first; ga[34].first = p; edgenode *s; //打印显示线路图 for(int i=0;i<MAX;i++) { // cout << ga[i].data; cout << ga[i].name; s = ga[i].first; while(s!=NULL) { cout << "->" << ga[s->adjvex].name; s = s->next; } cout << endl; } } /* 函数功能:对建立好的图进行广度优先遍历 函数输入输出:无 */ void Get_SUBWAY_LINE() { char str[2][5]; int start_i; cout <<"*************************************\n请输入起点与终点:"; while(scanf("%s %s",str[0],str[1])!=EOF)//输入两个站 { char find_flag = 0; int count=0,num=0,temp_num=1; edgenode *s; queue<vernode>q; for(int i=0;i<MAX;i++) { ga[i].visit_flag = 0;//未入列 } for(int i=0;i<MAX;i++) if(!strcmp(str[0],ga[i].name)) { start_i = i; break; } if(!ga[start_i].visit_flag)//未入列则入列 { q.push(ga[start_i]); ga[start_i].visit_flag = 1; } while(!q.empty())//寻找路径 { if(find_flag) { cout << "共需经过"<<count<<"站\n*************************************\n\n"; cout <<"*************************************\n请输入起点与终点:"; break;//找到路径 } count++; cout << "****第" << count <<"次搜索****"<<endl; for(int i=0;i<temp_num;i++)//取出同一层的各站点比对 { //查看队列头是否为终点,若是,break cout << q.front().name<<" "; if(!strcmp(str[1],q.front().name))//找到终点站 { find_flag = 1; break; } //队列头若不是终点,将它的下一层加入到队列中,并将它弹出 s = q.front().first; while(s!=NULL)//将下一层的广度都送入队列 { if(!ga[s->adjvex].visit_flag) { q.push(ga[s->adjvex]); num++; ga[s->adjvex].visit_flag = 1; } s = s->next; } q.pop(); }//for temp_num = num; num = 0; cout << endl; }//while(!q.empty()) }//while } void main() { creat(ga); Get_SUBWAY_LINE(); }