深度优先搜索与广度优先搜索

转载请注明本文出自大苞米的博客(),谢谢支持!

深度优先搜索(Depth First Search,DFS)主要思想:不撞南墙不回头

深度优先遍历的主要思想就是:首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问。

沿着某条路径遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有的顶点都被访问过为止。

图解:

分析:

通过上面的图例可以非常直观的了解深度优先搜索的工作方式。下面来分析一下如何用代码来实现它。 大家都知道,深度优先的主要思想就是“不撞南墙不回头”,“一条路走到黑”,如果遇到“墙”或者“无路可走”时再去走下一条路。

所以先规定好一个走路的规则,比如就按照右下左上顺时针的方式去尝试。

如上图僵尸的位置是起始点,先往右走,但是有堵墙走不了,所以按照规定尝试往下走。到达“1”的位置,此时重复刚才的步骤,先向右走可以走到“2”,再重复规则发现向右可以走到“3”,,再重复发现“下右左上”四个方向都不能走,这时候就退回“2”的位置尝试向下走。。。依次类推直到走到最终的目的地。

聪明的你肯定已经发现了“递归”是实现深度优先搜索的最好的方式。定义好规则然后就这样递归的循环下去直到走到终点,请看下面的伪代码:

void dfs() {// 判断是否到达终点if() {return;}// 尝试每一个可走方向(右下左上) for(i=0; i<n; i++){// 判断是否可走,可走调用递归尝试下一步,不可走则尝试该点的其他方向if () {// 继续下一步 dfs();}} } 代码:

程序中完整的深度优先搜索代码如下:

( int x, int y )throws Exception{int tx, ty;int[] pos ={ x, y };dfs_posList.add(pos);// 是否到达目的地if (mMapView[y][x] == 8){throw new Exception(“find”);}// 顺时针循环,右下左上四个方向for (int k = 0; k < 4; k++){tx = x + next[k][1];ty = y + next[k][0];// 是否出了边界boolean isOut = tx < 0 || tx >= mapWidth || ty < 0 || ty >= mapHeight;if (!isOut){// 是否是障碍物if (mMapView[ty][tx] == 0 && dfs_book[tx][ty] == 0 || mMapView[ty][tx] == 8){dfs_book[tx][ty] = 1;DFS(tx, ty);dfs_book[tx][ty] = 0;}}}}// 判断方向的数组int[][] next ={{ 0, 1 }, // 右{ 1, 0 }, // 下{ 0, -1 }, // 左{ -1, 0 } // 上};广度优先搜索(Breadth First Search, BFS)主要思想:层层递进

首先以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点,然后对每个相邻的顶点再访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

图解:

分析:

通过两个图例的对比,可以清楚的看到两种搜索算法的区别。 深度优先就是一条路走到底,然后再尝试下一条路。 广度优先就是走到一个点,将该点周围可走的点走完,然后再按同样规则走其他的点。(大家可以想像一下铺满的多米诺骨牌,将其中一块推倒其余周围的骨牌也会一层层扩散式的倒塌)

所以先规定好一个走路的规则,同样按照右下左上顺时针的方式去尝试。

如上图僵尸的位置是起始点,先往右走,但是有堵墙走不了,所以按照规定尝试往下走。到达“1”的位置,在“1”处可以知道四周能走的点只有“2”。“2”能走的点有“3”,“4”。来到“3”,发现没有可走的。来到“4”发现去可以去“5”。这样依次进行下去就完成了广度优先搜索。

我们可以通过“队列”来模拟上面的过程,伪代码如下:

void dfs() {Quene();offer(“起点”);=null) {// 从队列中取出一个点(并移除)p = quene.poll();// 循环尝试p点附近可走的点(右下左上) for(i=0; i<n; i++) {// 判断是否到达目的地if() {}// 判断是否可走,可走将该点加入到队列中,不可走则尝试该点的其他方向if () {queue.offer(“新点”);}}} }

完整代码:

BFS(){// 存储点的序列Queue<int[]> queue = new LinkedList<int[]>();int x, y;int[] pos ={ 0, 0 };queue.offer(pos);while (!queue.isEmpty()){// 从队列中取出并移除pos = queue.poll();bfs_posList.add(pos);// 顺时针循环,右下左上四个方向for (int k = 0; k < 4; k++){x = pos[0];y = pos[1];// 是否到达目的地if (mMapView[y][x] == 8){return;}x += next[k][1];y += next[k][0];// 是否出了边界boolean isOut = x < 0 || x >= mapWidth || y < 0 || y >= mapHeight;if (!isOut){// 是否是障碍物if (mMapView[y][x] == 0 && bfs_book[x][y] == 0 || mMapView[y][x] == 8){bfs_book[x][y] = 1;queue.offer(new int[]{ x, y });}}}}}int[][] next ={{ 0, 1 }, // 右{ 1, 0 }, // 下{ 0, -1 }, // 左{ -1, 0 } // 上};写在最后

相信通过上面的配图和讲解可以很清晰的理解深度优先搜索和广度优先搜索,如果今后有时间我争取再做一个最短路径的小Demo。

本例代码已经上传到我的github,感兴趣的可以下载来玩玩(纯属娱乐没啥实际价值):https://github.com/a396901990/PathFind

旅行,其实是需要具有一些流浪精神的,

深度优先搜索与广度优先搜索

相关文章:

你感兴趣的文章:

标签云: