البحث بالعرض (BFS)
آخر تحديث
يستكشف البحث بالعرض الرسم البياني مستوى تلو الآخر. بدءًا من عقدة المصدر، يزور أولًا جميع جيرانها المباشرين، ثم جميع الجيران غير المزارين لهؤلاء، وهكذا - متوسعًا نحو الخارج في حلقات ذات مسافة متزايدة. اضغط تشغيل بالأعلى لمشاهدته يتفرع من عقدة البداية طبقة تلو الأخرى.
يستخدم BFS طابورًا من نوع الوارد أولًا يخرج أولًا، وهو ما يفرض الترتيب مستوى تلو الآخر. لأنه يصل إلى العقد بترتيب مسافة القفزات، يجد BFS أقصر مسار (أقل عدد من الحواف) في رسم بياني غير موزون. يزور كل عقدة وحافة مرة واحدة، لذا يعمل في زمن O(V + E).
التعقيد الزمني والمكاني
| المقياس | التعقيد | ملاحظات |
|---|---|---|
| الزمن | O(V + E) | كل رأس وحافة تُزار مرة واحدة |
| المساحة | O(V) | الطابور + مجموعة المزارة، في أسوأ الحالات كل العقد |
| الاجتياز | مستوى تلو الآخر | أقرب العقد أولًا، في حلقات |
| أقصر مسار | نعم (غير موزون) | يصل إلى كل عقدة بأقل عدد من الحواف |
خطوة بخطوة
| الخطوة | ماذا يحدث |
|---|---|
| 1 | أضف عقدة المصدر إلى الطابور. |
| 2 | أخرج العقدة الأمامية وضع علامة أنها مزارة. |
| 3 | افحص كل واحد من جيرانها. |
| 4 | أضف إلى الطابور أي جار غير مزار وليس في الطابور بالفعل. |
| 5 | كرّر حتى يصبح الطابور فارغًا. |
مثال محلول
اجتياز هذا الرسم البياني بدءًا من العقدة 0، حيث 0-1 و0-2 و1-3 و2-3 و2-4 حواف:
| الخطوة | المزارة | الطابور (الحدود) |
|---|---|---|
| البداية | {} | [0] |
أخرج 0 | {0} | [1, 2] |
أخرج 1 | {0, 1} | [2, 3] |
أخرج 2 | {0, 1, 2} | [3, 4] |
أخرج 3 | {0, 1, 2, 3} | [4] |
أخرج 4 | {0, 1, 2, 3, 4} | [] (انتهى) |
متى تستخدم BFS
| استخدمه عندما | تجنّبه عندما |
|---|---|
| تحتاج إلى أقصر مسار في رسم بياني غير موزون | تحمل الحواف أوزانًا - استخدم Dijkstra بدلًا منه |
| من المرجح أن يكون الهدف قريبًا من المصدر | الرسم البياني عريض جدًا - قد يحتفظ الطابور بحدود ضخمة |
| تريد استكشاف رسم بياني بترتيب المستويات | تحتاج فقط إلى الوصول إلى أي عقدة، حيث يستخدم DFS ذاكرة أقل |
| تبحث عن المكوّنات المتصلة أو مسار بأقل عدد من القفزات | تحتاج إلى الترتيب الطوبولوجي أو كشف الدورات - DFS أنسب |
كود Breadth-First Search
تنفيذ نظيف وقابل للتشغيل لخوارزمية Breadth-First Search بلغات Python, JavaScript, Java, C++, C. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.
كود Breadth-First Search بلغة Python
1from collections import deque2
3
4def bfs(graph, start):5 visited = {start}6 queue = deque([start])7 order = []8 while queue:9 node = queue.popleft()10 order.append(node)11 for neighbor in graph[node]:12 if neighbor not in visited:13 visited.add(neighbor) # mark on enqueue, not dequeue14 queue.append(neighbor)15 return order16
17
18graph = {19 "A": ["B", "C"],20 "B": ["D", "E"],21 "C": ["F"],22 "D": [],23 "E": ["F"],24 "F": [],25}26
27print("BFS order:", " -> ".join(bfs(graph, "A")))كود Breadth-First Search بلغة JavaScript
1const graph = {2 A: ["B", "C"],3 B: ["D", "E"],4 C: ["F"],5 D: [],6 E: ["F"],7 F: [],8};9
10function bfs(start) {11 const visited = new Set([start]);12 const queue = [start];13 const order = [];14 while (queue.length > 0) {15 const node = queue.shift(); // Dequeue the oldest node16 order.push(node);17 for (const next of graph[node]) {18 if (!visited.has(next)) {19 visited.add(next);20 queue.push(next);21 }22 }23 }24 return order;25}26
27console.log("BFS from A:", bfs("A").join(" -> "));كود Breadth-First Search بلغة Java
1import java.util.ArrayDeque;2import java.util.List;3import java.util.Queue;4
5public class Main {6 public static void main(String[] args) {7 List<List<Integer>> adj = List.of(8 List.of(1, 2), // neighbors of 09 List.of(0, 3, 4), // neighbors of 110 List.of(0, 5),11 List.of(1),12 List.of(1, 5),13 List.of(2, 4)14 );15 boolean[] visited = new boolean[adj.size()];16 Queue<Integer> queue = new ArrayDeque<>();17 visited[0] = true;18 queue.add(0);19
20 StringBuilder order = new StringBuilder("BFS from 0:");21 while (!queue.isEmpty()) {22 int node = queue.poll();23 order.append(" ").append(node);24 // Mark neighbors when enqueued so nothing enters twice25 for (int next : adj.get(node)) {26 if (!visited[next]) {27 visited[next] = true;28 queue.add(next);29 }30 }31 }32 System.out.println(order);33 }34}كود Breadth-First Search بلغة C++
1#include <iostream>2#include <queue>3#include <vector>4
5void bfs(int start, const std::vector<std::vector<int>>& adj) {6 std::vector<bool> visited(adj.size(), false);7 std::queue<int> frontier;8 visited[start] = true;9 frontier.push(start);10 // Visit nodes level by level11 while (!frontier.empty()) {12 int node = frontier.front();13 frontier.pop();14 std::cout << node << " ";15 for (int next : adj[node]) {16 if (!visited[next]) {17 visited[next] = true;18 frontier.push(next);19 }20 }21 }22}23
24int main() {25 // 6-node undirected graph as an adjacency list26 std::vector<std::vector<int>> adj = {27 {1, 2}, // 028 {0, 3, 4}, // 129 {0, 5}, // 230 {1}, // 331 {1, 5}, // 432 {2, 4}, // 533 };34 std::cout << "BFS from node 0: ";35 bfs(0, adj);36 std::cout << "\n";37 return 0;38}كود Breadth-First Search بلغة C
1#include <stdbool.h>2#include <stdio.h>3
4#define N 65
6void bfs(int start, const int adj[N][N]) {7 bool visited[N] = {false};8 int queue[N]; // fixed-size queue: head chases tail9 int head = 0, tail = 0;10 visited[start] = true;11 queue[tail++] = start;12 // Visit nodes level by level13 while (head < tail) {14 int node = queue[head++];15 printf("%d ", node);16 for (int next = 0; next < N; next++) {17 if (adj[node][next] && !visited[next]) {18 visited[next] = true;19 queue[tail++] = next;20 }21 }22 }23}24
25int main(void) {26 // 6-node undirected graph as an adjacency matrix27 int adj[N][N] = {28 {0, 1, 1, 0, 0, 0},29 {1, 0, 0, 1, 1, 0},30 {1, 0, 0, 0, 0, 1},31 {0, 1, 0, 0, 0, 0},32 {0, 1, 0, 0, 0, 1},33 {0, 0, 1, 0, 1, 0},34 };35 printf("BFS from node 0: ");36 bfs(0, adj);37 printf("\n");38 return 0;39}أسئلة شائعة حول البحث بالعرض
ما هو التعقيد الزمني لـ BFS؟
O(V + E)، حيث V عدد الرؤوس وE عدد الحواف، لأنه يزور كل رأس مرة واحدة ويفحص كل حافة مرة واحدة. يستخدم O(V) من المساحة للطابور ومجموعة المزارة.هل يجد BFS أقصر مسار؟
ما الفرق بين BFS وDFS؟
متى ينبغي أن أستخدم BFS بدلًا من خوارزمية Dijkstra؟
O(V + E) دون طابور أولوية. تكون خوارزمية Dijkstra ضرورية عندما تحمل الحواف أوزانًا مختلفة؛ فتشغيل BFS الصرف على رسم بياني موزون يعطي المسار الأقل قفزات، لا الأقل تكلفة.