作者:狼与鹰的爱_340 | 来源:互联网 | 2023-06-11 09:33
bfs,dfs网上有很多关于它们的博文,学习的还是不要看我的,我只是看能不能用自己的话说出来。我也是小白。bfs中文名称是广度优先搜索,和dfs一样,两者都是搜索可以到达的所有
bfs ,dfs
网上有很多关于它们的博文,学习的还是不要看我的,我只是看能不能用自己的话说出来。我也是小白。
bfs 中文名称是广度优先搜索,和dfs 一样,两者都是搜索可以到达的所有状态。不同点是搜索顺序不同。dfs ,深度优先搜索,故名思议,会从一个状态出发,直到到达目标状态或者不满足某个条件而退回到上一个状态。很抽象是不是?没问题一开始我也看不懂,看完下面的例子再看,应该有点感觉了。
假如,你在一个迷宫寻找出口,来到了一个分岔口,选择其中一个,然后不断往前走,可能找到出口,可能又到达另一个分岔口,或者发现此路不通,此时你就要退回上一个分岔口,或者是起点。为了找到迷宫出口,我们需要把所有的状态记录下来,对当前的迷宫而言,这状态显然就是分岔口,是选择左呢,还是右呢,上还是下呢?都没关系,每一个都走走看。然后这有一个问题了,我们怎么知道这条路通不通呢?没办法,只能一直往下走才能知道通不通,通就最好,不通就退回上一个分岔口,选择另外一个方向。dfs 通常用递归实现。也可以用stack,stack的特点是 先进 后出,很符合dfs的特点,因为处于栈顶的元素(状态) ,就代表了我们目前所在的位置的上一个分岔口,如果此路不通,我们就把stack的元素pop()出来,选择另外一个方向,如果这分岔的所有方向都走过了,并且知道走不通,直接不再加入stack,选择此时的栈顶元素,即上上一个分岔口。当然,stack一开始是空的,因为你在起点还没遇到分岔口。当到达分岔口,把这分岔口入栈,然后选择一个方向往下走。用stack实现dfs比较麻烦,直接用递归最好了,递归本身就是用栈实现的。
如果给一个迷宫你叫你求到达出口的最短路径的长度,这时候我们若用dfs就显得繁琐了,因为我们需要走完整个迷宫,才能知道最短路径的长度。因为dfs是往深处搜索的,每次我们都要走完整条路才能确定这条路能不能到达出口,这对于求最短路径就不适合了。此时,bfs 上场了。它针对最短路径,最少操作非常合适。假设你现在依然在迷宫,并且会影分身,往前走,来到一个分岔口,它2个方向,你就分出一个分身,他走一个,你走一个,当然为了方便,我们假设你影分身很牛逼,分身不但可以分身,还能和分身交换位置。你和分身在不同方向同时往下走。不管先后顺序,你们都遇到了一个分岔口,重复上一步,影分身。继续,快变成篮球队的大家朝着不同方向继续前进了。运气非常好,分身们有一个到达了出口,此时你转移过去,恭喜了,顺利到达出口,并且此时你到达出口的分身走的路径是最短的,因为每一个分岔口都变出了分身,命令他们朝不同方向前进,意味着你从起点开始同时搜索所有可能的道路。可能你会吐槽我,分身一个走得慢,一个走得快,怎么办?很简单,让分身们和你同时走一步就可以了。这样,就能确保,到达出口的分身或者你是最短的路径。
每次前进一步,遇到分岔口,影分身,重复下去。回到这里,编程怎么实现了?怎么来管理这些影分身?可以想到,此时保存分岔口的选择就不太好了,很明显,根据上面的例子,我们要保存我们影分身的位置,每走一步跟新所有影分身的位置,而且每到达一个分岔口,我们影分身就会增加。这时要用队列来实现了。开始,队列只有一个,也就是你拉,拿出来,一直往前走,跟新此时的位置,去到分岔,变出几个影分身,并且加入队列,往前走,在一个一个拿出来,跟新他们的位置,加入队列尾,遇到分岔,就再次变出分身加入队列尾,一直重复下去,直到达出口。此时就break出来。
使用队列可以保证跟新完你和影分身当前位置,在开始跟新下一步。先进来的先处理。
到此吧,明天探讨一下题目。