1. 程式人生 > 其它 >演算法之BFS演算法框架

演算法之BFS演算法框架

技術標籤:演算法雜談演算法bfs

作者的話:最近有點時間,開始回來寫寫演算法相關的文章

BFS演算法框架

前言

BFS(廣度優先順序搜尋)和DFS(深度優先順序搜尋)是比較常用的演算法,其中DFS算是一種回溯演算法,在二叉樹中就相當於前序遍歷演算法。這裡先分析BFS演算法,為什麼呢?因為BFS比較簡單!廢話少說,直接上分析!

演算法分析

BFS相對於DFS最主要的區別在於:BFS找到的路徑一定是最短的,但是空間複雜度比DFS要大很多

BFS演算法的核心思想實際上就是將問題抽象成“圖”,從一個點開始,向周圍擴散。一般來說,我們寫BFS演算法常用的資料結構是“佇列”,每次都將一個節點周圍的所有節點加入佇列。

BFS演算法是出現的場景實際上就是讓你在一幅“圖”裡面找出從“起點”到“終點”的最短距離。把演算法本質搞清楚之後,問題都能化歸為基本問題。

如果上面的分析有點枯燥?不要緊,直接上栗子:

如走迷宮,有的格子周圍的牆壁不能走,讓你算從起點到終點的最短距離是多少?如果這個迷宮某些格子有“傳送門”呢?

再比如有兩個單詞,要求通過替換某些字母,把其中一個變成另外一個,每次只能替換一個字母,最少要替換幾次?

再比如連連看遊戲,消除兩個方塊的條件不僅僅是圖案相同,還要保證兩個方塊之間的最短連線不能多於兩個兩個拐點。你玩連連看,點選兩個座標,程式是如何找到最短連線的?如何判斷最短連線有幾個拐點?

。。。

其實,上面的例子無一不是一幅“圖”,讓你從起點走到終點,問最短路徑,實則BFS本質。

BFS演算法框架

上面分析完了,下面直接上演算法框架虛擬碼:

// 計算從起點 start 到終點 target 的最近距離
int BFS(Node start, Node target) {
    Queue<Node> q; // 核心資料結構
    Set<Node> visited; // 避免走回頭路

    q.offer(start); // 將起點加入佇列
    visited.add(start);
    int step = 0; // 記錄擴散的步數

    while (q not empty) {
        int sz = q.size();
        /* 將當前佇列中的所有節點向四周擴散 */
        for (int i = 0; i < sz; i++) {
            Node cur = q.poll();
            /* 劃重點:這裡判斷是否到達終點 */
            if (cur is target)
                return step;
            /* 將 cur 的相鄰節點加入佇列 */
            for (Node x : cur.adj())
                if (x not in visited) {
                    q.offer(x);
                    visited.add(x);
                }
        }
        /* 劃重點:更新步數在這裡 */
        step++;
    }
}

記住:因為BFS都是每次都是所有節點一起遍歷,因此BFS總能比較快地找到最短路徑。