华为机试之广度优先遍历

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

编译环境: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

华为机试之广度优先遍历_第1张图片


广度优先遍历:

这里我们需要用到队列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();
}




你可能感兴趣的:(华为机试之广度优先遍历)