zoukankan      html  css  js  c++  java
  • 华为机试之广度优先遍历

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

    编译环境: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();
    }




  • 相关阅读:
    Palindrome Linked List 解答
    Word Break II 解答
    Array vs Linked List
    Reverse Linked List II 解答
    Calculate Number Of Islands And Lakes 解答
    Sqrt(x) 解答
    Find Median from Data Stream 解答
    Majority Element II 解答
    Binary Search Tree DFS Template
    188. Best Time to Buy and Sell Stock IV
  • 原文地址:https://www.cnblogs.com/season-peng/p/6713571.html
Copyright © 2011-2022 走看看