前言
本文主要介绍一下Python的广度优先遍历算法,在Python中通过列表来模拟队列,完成一系列的广度优先遍历算法
一、广度优先搜索
在Python中,可以通过列表来模拟队列,通过append()函数来将新元素插入队列和del()函数来删除队首元素,选择队列存储结构的原因是:队列的存储机制为先进先出,而广度优先遍历恰好需要保证先访问已访问顶点的未访问邻接点;队列只支持两个基本操作,入队和出队,相比于其他数据结构队列的操作简单。
二、图的广度优先遍历
简介
广度优先搜索遍历类似于树的按层次遍历的过程。其过程为:假设从图中的某顶点v出发,在访问了v之后依次访问v的各个未曾被访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作为起始点。重复上述过程,直至图中所有顶点都被访问到为止。
问题描述
在本题中,读入一个无向图的邻接矩阵(即数组表示),建立无向图并按照以上描述中的算法遍历所有顶点,输出遍历顶点的顺序。
【输入形式】
输入的第一行包含一个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数0或1,对于第i行的第j个0或1,1表示第i个顶点和第j个顶点有直接连接,0表示没有直接连接。当i和j相等的时候,保证对应的整数为0。
输入保证邻接矩阵为对称矩阵,即输入的图一定是无向图。
【输出形式】
只有一行,包含n个整数,表示按照题目描述中的广度优先遍历算法遍历整个图的访问顶点顺序。每个整数后输出一个空格,并请注意行尾输出换行。
【样例输入】
4
0 0 0 1
0 0 1 1
0 1 0 1
1 1 1 0
【样例输出】
0 3 1 2
【提示】
在本题中,需要熟练掌握图的邻接矩阵存储方式。在建立完成无向图之后,需要严格按照题目描述的遍历顺序对图进行遍历。另外,算法中描述的FirstAdjVex函数和NextAdjVex函数,需要认真的自行探索并完成。在本题中需要使用队列结构,需要对队列的概念进行复习。
通过这道题目,应该能够对图的广度优先搜索建立更加直观和清晰的概念。
图的广度优先遍历算法:
n=int(input()) V=[] for i in range(n): lst=list(map(int,input().split())) V.append(lst) Q=[0] #队列 visit=[False for i in range(n)] #判断是否已经访问过 while len(Q)!=0: t=Q.pop(0) #出队 print(t,end=' ') visit[t]=True #访问 for i in range(n): if V[t][i]==1 and visit[i]==False and (i not in Q): Q.append(i) #未访问过,入队 print('\n')
三、经典例题
1.现已知一个大小为N*M的地图,地图中只有可能出现两个数字:0或1,现规定如果位于数字为0的格子上,则下一步只能往相邻四个格子中数字为1的格子走,如果位于数字为1的格子上,则下一步只能往相邻四个格子中数字为0的格子走。如果给定起点格子,则可以向上下左右四个方向移动,且同一个格子不能重复走,求能在地图中到达多少格子?
具体算法如下(从(3,3)开始走):
Q=[] class grid: def __init__(self,row,col): self.row=row self.col=col def bfs(val,startrow,startcol): row=len(val) col=len(val[0]) arrived=[[False for j in range(int(col))] for i in range (int(row))] moverow=[0,1,0,-1] movecol=[1,0,-1,0] ans=1 Q.append(grid(int(startrow),int(startcol))) arrived[int(startrow)-1][int(startcol)-1]=True while len(Q)!=0: cur=Q.pop(0) for i in range(4): newrow=cur.row+moverow[i] newcol=cur.col+movecol[i] if newrow>row or newrow<=0 or newcol>col or newcol<=0: continue if arrived[newrow-1][newcol-1]==False and val[newrow-1][newcol-1]!=val[cur.row-1][cur.col-1]: Q.append(grid(newrow,newcol)) arrived[newrow-1][newcol-1]=True ans+=1 return ans val=[[1,0,1,1],[1,0,1,0],[0,1,0,1],[0,0,1,1]] print(bfs(val,3,3))
算法分析如下:
本程序实现了一个基于广度优先搜索(BFS)的算法用于计算矩阵中与给定坐标(起点)上的元素值不同的元素的数量。其中,矩阵是由一个二维列表表示的。该算法主要的实现过程如下:
1. 首先,定义了一个名为Q的列表作为存储待访问元素的队列,并定义了一个名为grid的类来存储矩阵中的单个元素的行和列坐标信息。
2. 其次,定义了一个名为arrived的二维列表,用于存储已经访问到的元素的信息,并将其初始化为False。
3. 接着,定义了两个列表(moverow和movecol),用于存储探索相邻元素时的行和列移动方向。这里使用的是上、右、下、左四个方向。
4. 将起始元素(即给定坐标)的行、列信息存储在grid实例中,并将其添加至Q中,同时将arrived矩阵中对应位置设置为True。
5. 开始BFS的循环,直到队列Q中无元素为止。在每次循环中,弹出队列Q的头部元素(即当前待访问元素),并依次探索其相邻元素,判断其是否已经被访问,并将未访问过的元素添加至队列Q中。
6. 每次添加未访问过的元素时,都要将其对应的arrived矩阵中的位置设置为True,并且计数器ans加1。
7. 循环结束后,ans即为与起点上的元素值不同的元素的数量。
总的来说,该算法是比较简单易懂的,适用于矩阵中元素的遍历和探索问题。但是需要注意的是,该算法的时间复杂度为O(n^2),其中n为矩阵的大小,因此对于较大的矩阵,其效率可能会比较低。
总结
本章主要简单介绍了广度优先遍历,需要对队列进行灵活的运用