广度优先搜索算法

                                                  广度优先搜索(BFS)

         这个是第一个研究的课题,广度优先搜索也叫宽度优先搜索,英文为Breadth First Searth,开始看的时候一头雾水,基本也能懂大致意思,但是还不是真正的理解,今天又仔细看看,大致理解上又更深了一层吧。

          下面来总结下,自己的一些体会,以及对它的独到的理解。

          大的方面来说它是一种按照层次类似树的形式,按层次遍历的过程。

         假设从某一个顶点V出发,访问v之后,(访问可理解为,达到了该点,并且函数可以并且已经调用了),然后找出v的所有邻接点,依次访问,如果v的邻接点有(v1,v2)的话,那么下一步在接着从v1,和v2出发访问v1的邻接点,v2的邻接点,然后知道图中所有的点都被访问完为止。

              

        上面是大致思路,进一步思考,在访问v1的邻接点的时候,必然会找到它的前继就是上一个给它传送的那个点,此处是v,就会发生重复了,也就是说,在找后面的邻接点的时候,我们最好要保证那些已经访问过的点,这时候不再访问了,否则就是死循环了,这里就要要求我们有个标志去记录那些已经访问过的点,让他们跟那些未访问的不一样。

       前面提到那个层次性,就是首先访问跟v为第一步的点,然后第一步的点,邻接点,也就是v的第二层点,那么我们怎么才能体现出这个层次性呢?

         最笨的方法是,可以创建多个数组,一步一个数组,第一步的为数组名为1,第二步为数组2,第三步的为数组3,。。。。。依次创建,这样对于小型的图还可以但是大型的图就浪费空间很大,这样还很不灵活,数组都是固定的,对于每一个点,它的邻接点并不是固定的,所以我们想到要用动态数组,并且这个动态数组可以为每一步服务,而不必每次都要创建一个新的数组。

          动态数组中首先想到用栈来实现,先把v放进去,第一层,然后以v为起点开始找它的邻接点v1,v2,把v1,v2入栈,然后在找v1,v2的邻接点的时候就会发现,当找到v1的邻接点之后,我们把v1先出栈,然后把它的邻接点入栈,这时候,v2就会被退到栈尾,那么下一次出栈的就是v1的邻接点而不是v2体现不出层次性了。

        

      由上面的分析,发现栈在这里不合适,那么我们选用队列来实现,因为每次进来的点都排在队头,然后他们依次离开队的时候都把他们的邻接点全部入队,都在队尾,不会影响,队头上一层的那些点,然后依次类推下去,上一层的邻接点全部出队列之后,就剩下的都是上一层队列那些点所有的邻接点了。


   下面我们用文字把大致的过程思路给理一下

   1.找到一个标志把所有点都表示下,未访问的,和访问过的要区别开来。

   2,随机找到一个点,从当前点开始,放到队列的队头。

   3,找到队头的元素,删去,并且找到该点所有的邻接点,把那些没有访问过的点放到队尾去。

  4,当最后队列空的时候就把所有点遍历完了。


然后我们用c语言来表示一下。

对于标志我们用数组visit[]来表示,该数组保存了所有点,下标代表该点,元素值为true,表示访问过,反之,表示未访问过。

/*EnQueue 入队列

G.vexnum    图的顶点数目

DeQueue(Q,u)   删除队头元素并赋值为u

QueueEmpty(Q) 判断队头元素是否为空

FirstAdjvex(G,u) u的第一个邻接点

NextAdjVex(G,u,w)

u的除了w之外的邻接点,如果没有,则返回-1*/



for(i=0;i<G.vexnum;i++)

visit[i]=false;//首先所有点都初始化为未访问过 

visit[0]=true;//此处假定是从第一个点开始访问,就把该点值变为true 

EnQueue(Q);//然后该点就入队列 

while(!QueueEmpty(Q)){//当队列为空的时候就把所有点遍历完了 

    DeQueue(Q,v);//每次都是找到队头那个点,删去它,然后下面找它的所有邻接点然后把这些邻接点都放到队列的尾部去 

    for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)){//此循环是找所有队头元素邻接点的 

        if(!visit[w]){//if是用来筛选出那些已经访问过的点 

            visit[w]=true;//如果该点没有被访问的话,那么就把该点访问了(值变为true),同时加到队尾去 

            EnQueue(Q);//把该点加到队尾去 

            }

        }

    }

如果你用的是严蔚敏版的c语言数据结构书的话,就会发现其实这里的算法,跟课本上还不太一样,少了开头的一个对所有点的一个大循环,事实上,这个大循环的作用是使该算法更全面能处理非连通图,因为对于连通图来说,从某一个点出发按层次结构必然会将所有点访问完的,除非该点与那个“某一点”出发的搜索图本来就不连通,所以上面的算法只是使用于连通图,非连通图要加上一个对所有点进行一次遍历的排查,发现如果有点还未访问,那么就从该点开始进行上面的算法,把以该点为起始点的点都遍历完。


这样一步一步的写出这样的过程,思考为什么要这么做,能让我更清晰知道发明该算法的人的思考过程,只有这样才能更深刻的理解该算法,不然,我们都只是停留在,嗯,是这样,就是弄个队列嘛,保存下,然后就好了,就是外面加个大循环嘛,为什么呢?

经过仔细的分析,一步一步的推导,从本文也许可以找到答案。

因为今天去调查了班级里一些还算相当不错的同学,其实他们对这个都是支支吾吾的不是特别的明白,故认真的总结本文,来加深自己的对广度优先搜索算法理解。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值