• 华为机试之广度优先遍历


    在华为的论坛上看到了下面这个题目,想着最近刚好没事,就来写一下。

    编译环境: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 <<"*************************************
    请输入起点与终点:";
    	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<<"站
    *************************************
    
    ";
    				cout <<"*************************************
    请输入起点与终点:";
    				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();
    }




  • 相关阅读:
    UIWebView
    Do not access Object.prototype method 'hasOwnProperty' from target object.eslintno-prototype-builtins
    TypeError: ### is null,空指针导致的报错
    antd里面的Table渲染多出来数据问题
    VSCode保存时代码格式化
    前端GIT规范
    实现简单的数组去重?
    提取对象数组的公共元素
    Git常用面试知识点
    taro自定义导航标题(可根据路由参数或者接口返回字段定义页面导航标题)
  • 原文地址:https://www.cnblogs.com/season-peng/p/6713571.html
Copyright © 2020-2023  润新知