廣度優先搜尋BFS

介紹

節點選項是用 先進先出(FIFO) 方式進行管理,所以可以使用佇列的資料結構

廣度優先搜尋(BFS)是一種圖形搜尋演算法,從圖的起點開始搜尋,先遍歷所有距離起點為1的節點,再遍歷所有距離起點為2的節點,以此類推直到所有可達節點都被遍歷。 BFS適用於需要找到最短路徑或最少步驟的問題,例如迷宮遊戲或圖形路徑問題

虛擬碼

以下是使用 JavaScript 撰寫的 BFS 演算法的簡易虛擬碼範本:

// 假設圖形表示為鄰接表 adjacency list 的形式
// graph: 圖形,start: 起點,end: 終點
function BFS(graph, start, end) {
// 用來保存已訪問的節點
const visited = new Set();
// 用來保存尚未探索的節點
const queue = [];
// 將起點加入佇列
queue.push(start);
// 標記起點已訪問
visited.add(start);

while (queue.length > 0) {
// 取出佇列中的下一個節點
const node = queue.shift();
// 如果找到終點,返回路徑
if (node === end) {
return true; // 找到終點
}
// 對節點的所有鄰接節點進行訪問
for (const neighbor of graph[node]) {
// 如果鄰接節點未被訪問,加入佇列
if (!visited.has(neighbor)) {
queue.push(neighbor);
// 標記鄰接節點已訪問
visited.add(neighbor);
}
}
}
return false; // 無法到達終點
}

graph = {
1: [2, 3],
2: [1, 4],
3: [1, 4],
4: [2, 3, 5],
5: [4]
};

console.log(BFS(graph, 1, 5));

這個 BFS 實現使用 Set 來保存已訪問的節點,使用佇列來保存尚未探索的節點,並在佇列中使用先進先出的方式來探索圖形。

複雜度

時間複雜度

$O(V+E)$
其中 V 是節點的數量,E 是邊的數量。在最壞的情況下,BFS 將遍歷圖形中的每個節點和每條邊,因此它的時間複雜度與圖形的大小成正比。

空間複雜度

$O(V)$

因為BFS 使用了一個佇列來保存尚未探索的節點,其中 V 是節點的數量。在最壞的情況下,BFS 需要將圖形中的每個節點都加入佇列,因此空間複雜度也與圖形的大小成正比。

實戰

637. Average of Levels in Binary Tree

題目說明

給定一棵二元數,以數組的形式返回每一層節點的平均值。實際答案在 $10^5$ 以內的答案將被接受。

解法

使用佇列方式層次遍歷,並累加每一層節點的值,計算出每一層節點的平均值,並儲存於陣列中傳回。

/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var averageOfLevels = function(root) {
let queue = [root];
let target = [];
while (queue.length > 0) {
let qlen = queue.length;
let row = 0;
for (let i = 0; i < qlen; i++) {
let {val, left, right} = queue.shift();
row += val;
if (left) queue.push(left);
if (right) queue.push(right);
}
target.push(row/qlen);
}
return target;
};