logo

그래프의 너비 우선 검색(BFS)

너비 우선 검색(BFS) 기본이다 그래프 순회 알고리즘 . 여기에는 레벨별로 그래프의 연결된 모든 노드를 방문하는 작업이 포함됩니다. 이번 글에서는 개념에 대해 알아보겠습니다. BFS 그래프에 어떻게 효과적으로 적용할 수 있는지

내용의 테이블



그래프에 대한 너비 우선 검색(BFS):

너비 우선 검색(BFS) 다음 깊이 수준의 정점으로 이동하기 전에 현재 깊이에서 그래프의 모든 정점을 탐색하는 그래프 순회 알고리즘입니다. 지정된 정점에서 시작하여 다음 수준의 이웃으로 이동하기 전에 모든 이웃을 방문합니다. BFS 일반적으로 경로 찾기, 연결된 구성 요소 및 그래프의 최단 경로 문제에 대한 알고리즘에 사용됩니다.

그래프용 BFS와 트리용 BFS의 관계:

그래프의 너비 우선 순회(BFS)는 다음과 유사합니다. 트리의 너비 우선 순회 .

여기서 유일한 문제는 나무 , 그래프 사이클이 포함될 수 있으므로 동일한 노드에 다시 올 수 있습니다. 노드를 두 번 이상 처리하지 않기 위해 정점을 두 가지 범주로 나눕니다.



  • 방문 및
  • 방문하지 않았습니다.

부울 방문 배열은 방문한 정점을 표시하는 데 사용됩니다. 단순화를 위해 시작 정점에서 모든 정점에 도달할 수 있다고 가정합니다. BFS 용도 그래프 알고리즘에 대한 너비 우선 검색(BFS):

BFS 알고리즘에 대해 논의해 보겠습니다.

  1. 초기화: 시작 노드를 큐에 넣고 방문한 것으로 표시합니다.
  2. 탐구: 대기열이 비어 있지 않은 동안:
    • 대기열에서 노드를 빼고 방문합니다(예: 해당 값 인쇄).
    • 대기열에서 제거된 노드의 방문하지 않은 각 이웃에 대해 다음을 수행합니다.
      • 이웃을 대기열에 추가합니다.
      • 이웃을 방문한 것으로 표시합니다.
  3. 종료: 대기열이 빌 때까지 2단계를 반복합니다.

이 알고리즘은 시작 노드부터 시작하여 그래프의 모든 노드를 너비 우선 방식으로 방문하도록 보장합니다.



BFS 알고리즘은 어떻게 작동합니까?

루트부터 시작하여 특정 수준의 모든 노드를 먼저 방문하고 모든 노드를 방문할 때까지 다음 수준의 노드를 순회합니다.

이를 위해 대기열이 사용됩니다. 현재 수준의 방문하지 않은 인접한 모든 노드는 대기열로 푸시되고 현재 수준의 노드는 방문한 것으로 표시되어 대기열에서 팝됩니다.

삽화:

다음 예제를 통해 알고리즘의 작동을 이해해 보겠습니다.

1 단계: 처음에는 대기열 및 방문한 배열이 비어 있습니다.

대기열 및 방문 배열은 처음에는 비어 있습니다.

2 단계: 노드 0을 대기열에 푸시하고 방문한 것으로 표시합니다.

노드 0을 대기열에 푸시하고 방문한 것으로 표시합니다.

노드 0을 대기열에 푸시하고 방문한 것으로 표시합니다.

3단계: 대기열 앞의 노드 0을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열 앞의 노드 0을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 넣습니다.

대기열 앞의 노드 0을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 넣습니다.

4단계: 대기열의 앞부분에서 노드 1을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열 앞의 노드 1을 제거하고 방문하지 않은 이웃을 방문하여 푸시합니다.

대기열 앞의 노드 1을 제거하고 방문하지 않은 이웃을 방문하여 푸시합니다.

5단계: 대기열 앞의 노드 2를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열 앞의 노드 2를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열 앞의 노드 2를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

6단계: 대기열 앞의 노드 3을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.
노드 3의 모든 이웃이 방문되는 것을 볼 수 있으므로 대기열 앞에 있는 다음 노드로 이동합니다.

대기열 앞의 노드 3을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열 앞의 노드 3을 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

7단계: 대기열의 앞부분에서 노드 4를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.
노드 4의 모든 이웃이 방문되는 것을 볼 수 있으므로 대기열 앞에 있는 다음 노드로 이동합니다.

대기열 앞의 노드 4를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

대기열의 앞부분에서 노드 4를 제거하고 방문하지 않은 이웃을 방문하여 대기열에 밀어 넣습니다.

이제 Queue가 비어 있으므로 이러한 반복 프로세스를 종료합니다.

인접 목록을 사용하여 그래프용 BFS 구현:

C++
#include  #include  #include  using namespace std; // Function to perform Breadth First Search on a graph // represented using adjacency list void bfs(vector>& adjList, int startNode, 벡터 & 방문) { // BFS 대기열에 대한 대기열 생성 큐;  // 현재 노드를 방문한 것으로 표시하고 대기열에 넣습니다.[startNode] = true;  q.push(startNode);  // 대기열을 반복합니다. while (!q.empty()) { // 대기열에서 정점을 제거하고 인쇄합니다. int currentNode = q.front();  q.pop();  시합<< currentNode << ' ';  // Get all adjacent vertices of the dequeued vertex  // currentNode If an adjacent has not been visited,  // then mark it visited and enqueue it  for (int neighbor : adjList[currentNode]) {  if (!visited[neighbor]) {  visited[neighbor] = true;  q.push(neighbor);  }  }  } } // Function to add an edge to the graph void addEdge(vector>& adjList, int u, int v) { adjList[u].push_back(v); } int main() { // 그래프의 정점 수 int vertices = 5;  // 그래프 벡터의 인접 목록 표현> adjList(정점);  // 그래프에 가장자리를 추가합니다. addEdge(adjList, 0, 1);  addEdge(adjList, 0, 2);  addEdge(adjList, 1, 3);  addEdge(adjList, 1, 4);  addEdge(adjList, 2, 4);  // 모든 정점을 방문하지 않은 벡터로 표시 방문(정점, 거짓);  // 정점 0부터 시작하여 BFS 탐색을 수행합니다. cout<< 'Breadth First Traversal starting from vertex '  '0: ';  bfs(adjList, 0, visited);  return 0; }>
#include  #include  #define MAX_VERTICES 100 // Structure to represent a node in adjacency list struct Node {  int data;  struct Node* next; }; // Function to create a new node struct Node* createNode(int data) {  struct Node* newNode  = (struct Node*)malloc(sizeof(struct Node));  newNode->데이터 = 데이터;  newNode->다음 = NULL;  새로운 노드를 반환; } // 그래프에 간선을 추가하는 함수 void addEdge(struct Node* adjList[], int u, int v) { struct Node* newNode = createNode(v);  newNode->next = adjList[u];  adjList[u] = newNode; } // 그래프에서 너비 우선 검색을 수행하는 함수 // 인접 목록을 사용하여 표현됨 void bfs(struct Node* adjList[], int vertices, int startNode, int Visit[]) { // BFS에 대한 큐 생성 int queue[ MAX_VERTICES];  int 앞 = 0, 뒤 = 0;  // 현재 노드를 방문한 것으로 표시하고 대기열에 넣습니다.[startNode] = 1;  대기열[rear++] = startNode;  // 큐를 반복합니다. while (front != Rear) { // 큐에서 정점을 빼내고 인쇄합니다. int currentNode = queue[front++];  printf('%d ', currentNode);  // 대기열에서 제거된 정점의 모든 인접 정점을 가져옵니다. // currentNode 인접 정점을 방문하지 않은 경우 // 방문한 것으로 표시하고 대기열에 넣습니다. struct Node* temp = adjList[currentNode];  while (temp != NULL) { int neighbor = temp->data;  if (!visited[이웃]) { 방문[이웃] = 1;  대기열[리어++] = 이웃;  } 임시 = 임시->다음;  } } } int main() { // 그래프의 정점 수 int vertices = 5;  // 그래프의 인접 목록 표현 struct Node* adjList[vertices];  for (int i = 0; i< vertices; ++i)  adjList[i] = NULL;  // Add edges to the graph  addEdge(adjList, 0, 1);  addEdge(adjList, 0, 2);  addEdge(adjList, 1, 3);  addEdge(adjList, 1, 4);  addEdge(adjList, 2, 4);  // Mark all the vertices as not visited  int visited[vertices];  for (int i = 0; i < vertices; ++i)  visited[i] = 0;  // Perform BFS traversal starting from vertex 0  printf(  'Breadth First Traversal starting from vertex 0: ');  bfs(adjList, vertices, 0, visited);  return 0; }>
자바
import java.util.LinkedList; import java.util.Queue; // Class to represent a graph using adjacency list class Graph {  int vertices;  LinkedList [] 조정목록;  @SuppressWarnings('unchecked') Graph(int vertices) { this.vertices = vertices;  adjList = 새로운 LinkedList[정점];  for (int i = 0; i< vertices; ++i)  adjList[i] = new LinkedList();  }  // Function to add an edge to the graph  void addEdge(int u, int v) { adjList[u].add(v); }  // Function to perform Breadth First Search on a graph  // represented using adjacency list  void bfs(int startNode)  {  // Create a queue for BFS  Queue 대기열 = 새로운 LinkedList();  boolean[] 방문함 = new boolean[vertices];  // 현재 노드를 방문한 것으로 표시하고 대기열에 넣습니다.[startNode] = true;  queue.add(startNode);  // 대기열을 반복합니다. while (!queue.isEmpty()) { // 대기열에서 정점을 제거하고 인쇄합니다. int currentNode = queue.poll();  System.out.print(currentNode + ' ');  // 대기열에서 제거된 모든 인접 정점을 가져옵니다. // 정점 currentNode 인접 정점을 방문하지 않은 경우 // 방문한 것으로 표시하고 // 대기열에 넣습니다. for (int neighbor : adjList[currentNode]) { if (!visited[neighbor] ) { 방문[이웃] = true;  queue.add(이웃);  } } } } } public class Main { public static void main(String[] args) { // 그래프의 정점 수 int vertices = 5;  // 그래프 생성 Graph graph = new Graph(vertices);  // 그래프에 간선을 추가합니다. graph.addEdge(0, 1);  graph.addEdge(0, 2);  graph.addEdge(1, 3);  graph.addEdge(1, 4);  graph.addEdge(2, 4);  // 정점 0부터 시작하여 BFS 순회를 수행합니다. System.out.print( '정점 0에서 시작하는 너비 우선 순회: ');  그래프.bfs(0);  } }>
파이썬3
from collections import deque # Function to perform Breadth First Search on a graph # represented using adjacency list def bfs(adjList, startNode, visited): # Create a queue for BFS q = deque() # Mark the current node as visited and enqueue it visited[startNode] = True q.append(startNode) # Iterate over the queue while q: # Dequeue a vertex from queue and print it currentNode = q.popleft() print(currentNode, end=' ') # Get all adjacent vertices of the dequeued vertex # If an adjacent has not been visited, then mark it visited and enqueue it for neighbor in adjList[currentNode]: if not visited[neighbor]: visited[neighbor] = True q.append(neighbor) # Function to add an edge to the graph def addEdge(adjList, u, v): adjList[u].append(v) def main(): # Number of vertices in the graph vertices = 5 # Adjacency list representation of the graph adjList = [[] for _ in range(vertices)] # Add edges to the graph addEdge(adjList, 0, 1) addEdge(adjList, 0, 2) addEdge(adjList, 1, 3) addEdge(adjList, 1, 4) addEdge(adjList, 2, 4) # Mark all the vertices as not visited visited = [False] * vertices # Perform BFS traversal starting from vertex 0 print('Breadth First Traversal starting from vertex 0:', end=' ') bfs(adjList, 0, visited) if __name__ == '__main__': main()>
씨#
using System; using System.Collections.Generic; // Class to represent a graph using adjacency list class Graph {  int vertices;  List [] 조정목록;  공개 그래프(int 정점) { this.vertices = 정점;  adjList = 새 목록 [ 정점 ];  for (int i = 0; i< vertices; ++i)  adjList[i] = new List ();  } // 그래프에 간선을 추가하는 함수 public void AddEdge(int u, int v) { adjList[u].Add(v); } // 그래프에서 너비 우선 검색을 수행하는 함수 // 인접 목록을 사용하여 표현됨 public void BFS(int startNode) { // BFS Queue에 대한 큐 생성 대기열 = 새 대기열 ();  bool[] 방문 = 새로운 bool[vertices];  // 현재 노드를 방문한 것으로 표시하고 대기열에 넣습니다.[startNode] = true;  queue.Enqueue(startNode);  // 대기열을 반복합니다. while (queue.Count != 0) { // 대기열에서 정점을 제거하고 인쇄합니다. int currentNode = queue.Dequeue();  Console.Write(currentNode + ' ');  // 대기열에서 제거된 모든 인접 정점을 가져옵니다. // 정점 currentNode 인접 정점을 방문하지 않은 경우 // 방문한 것으로 표시하고 // 대기열에 넣습니다. foreach(int neighbor in adjList[currentNode]) { if (!visited[neighbor] ) { 방문[이웃] = true;  queue.Enqueue(이웃);  } } } } } class MainClass { public static void Main(string[] args) { // 그래프의 정점 수 int vertices = 5;  // 그래프 생성 Graph graph = new Graph(vertices);  // 그래프에 간선을 추가합니다. graph.AddEdge(0, 1);  graph.AddEdge(0, 2);  graph.AddEdge(1, 3);  graph.AddEdge(1, 4);  graph.AddEdge(2, 4);  // 정점 0부터 BFS 순회를 수행합니다. Console.Write( '정점 0에서 시작하는 너비 우선 순회: ');  그래프.BFS(0);  } }>
자바스크립트
// Class to represent a graph using adjacency list class Graph {  constructor() {  this.adjList = {};  }  // Function to add an edge to the graph  addEdge(u, v) {  if (!this.adjList[u]) this.adjList[u] = [];  this.adjList[u].push(v);  }  // Function to perform Breadth First Search on a graph represented using adjacency list  bfs(startNode) {  // Create a queue for BFS  const queue = [];  const visited = new Array(Object.keys(this.adjList).length).fill(false);  // Mark the current node as visited and enqueue it  visited[startNode] = true;  queue.push(startNode);  // Iterate over the queue  while (queue.length !== 0) {  // Dequeue a vertex from queue and print it  const currentNode = queue.shift();  console.log(currentNode + ' ');  // Get all adjacent vertices of the dequeued vertex currentNode  // If an adjacent has not been visited, then mark it visited and enqueue it  for (const neighbor of this.adjList[currentNode] || []) {  if (!visited[neighbor]) {  visited[neighbor] = true;  queue.push(neighbor);  }  }  }  } } // Create a graph const graph = new Graph(); // Add edges to the graph graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 3); graph.addEdge(1, 4); graph.addEdge(2, 4); // Perform BFS traversal starting from vertex 0 console.log('Breadth First Traversal starting from vertex 0: '); graph.bfs(0);>

산출
Breadth First Traversal starting from vertex 0: 0 1 2 3 4>

시간 복잡도: O(V+E), 여기서 V는 노드 수이고 E는 간선 수입니다.
보조 공간: 오(V)

BFS(Breadth-First Search) 알고리즘의 복잡성 분석:

BFS 알고리즘의 시간 복잡도: O(V + E)

  • BFS는 그래프의 모든 정점과 가장자리를 탐색합니다. 최악의 경우 모든 정점과 가장자리를 한 번씩 방문합니다. 따라서 BFS의 시간 복잡도는 O(V + E)입니다. 여기서 V와 E는 주어진 그래프의 정점과 가장자리의 수입니다.

BFS 알고리즘의 공간 복잡도: O(V)

  • BFS는 큐를 사용하여 방문해야 할 정점을 추적합니다. 최악의 경우 큐에는 그래프의 모든 정점이 포함될 수 있습니다. 따라서 BFS의 공간 복잡도는 O(V)입니다. 여기서 V와 E는 주어진 그래프의 정점과 가장자리의 수입니다.

그래프에서의 BFS 적용:

BFS는 다음을 포함하여 그래프 이론 및 컴퓨터 과학에 다양한 응용 프로그램을 보유하고 있습니다.

  • 최단 경로 찾기: BFS는 비가중 그래프에서 두 노드 사이의 최단 경로를 찾는 데 사용될 수 있습니다. 순회 중에 각 노드의 상위 노드를 추적함으로써 최단 경로를 재구성할 수 있습니다.
  • 사이클 감지: BFS를 사용하여 그래프에서 주기를 감지할 수 있습니다. 순회 중에 노드를 두 번 방문하면 주기가 있음을 나타냅니다.
  • 연결된 구성 요소: BFS는 그래프에서 연결된 구성 요소를 식별하는 데 사용할 수 있습니다. 연결된 각 구성 요소는 서로 도달할 수 있는 노드 집합입니다.
  • 토폴로지 정렬: BFS는 방향성 비순환 그래프(DAG)에서 위상 정렬을 수행하는 데 사용될 수 있습니다. 위상 정렬은 임의의 모서리(u, v)에 대해 u가 순서대로 v 앞에 나타나도록 노드를 선형 순서로 정렬합니다.
  • 이진 트리의 레벨 순서 순회: BFS는 이진 트리의 레벨 순서 순회를 수행하는 데 사용될 수 있습니다. 이 순회는 다음 레벨로 이동하기 전에 동일한 레벨의 모든 노드를 방문합니다.
  • 네트워크 라우팅: BFS는 네트워크의 두 노드 사이의 최단 경로를 찾는 데 사용할 수 있으므로 네트워크 프로토콜에서 데이터 패킷을 라우팅하는 데 유용합니다.

그래프의 너비 우선 검색 또는 BFS 관련 문제:

예 아니오

문제

관행
1. 무방향 그래프에서 주어진 노드의 레벨 찾기 링크
2. 왼쪽 상단에서 오른쪽 하단까지의 경로에서 최대 인접 차이를 최소화합니다. 링크
10. 주어진 Matrix의 목적지에 필요한 셀 값으로 도달 가능한지 확인 링크

그래프의 너비 우선 검색(BFS)에 대한 FAQ:

질문 1: BFS란 무엇이며 어떻게 작동하나요?

답변: BFS는 다음 레벨로 이동하기 전에 주어진 레벨의 모든 꼭지점을 방문하여 그래프를 체계적으로 탐색하는 그래프 순회 알고리즘입니다. 시작 정점에서 시작하여 대기열에 추가하고 방문한 것으로 표시합니다. 그런 다음 대기열에서 정점을 제거하고 방문하고 방문하지 않은 모든 이웃을 대기열에 추가합니다. 이 프로세스는 대기열이 빌 때까지 계속됩니다.

질문 2: BFS의 용도는 무엇입니까?

답변: BFS에는 비가중 그래프에서 최단 경로 찾기, 그래프에서 주기 감지, 방향성 비순환 그래프(DAG)의 위상학적 정렬, 그래프에서 연결된 구성 요소 찾기, 미로 및 스도쿠와 같은 퍼즐 풀기 등 다양한 응용 프로그램이 있습니다.

질문 3: BFS의 시간 복잡도는 얼마입니까?

답변: BFS의 시간 복잡도는 O(V + E)입니다. 여기서 V는 정점 수이고 E는 그래프의 간선 수입니다.

문자열.자바 포함

질문 4: BFS의 공간 복잡도는 무엇입니까?

답변: BFS의 공간 복잡도는 O(V)입니다. 방문해야 할 정점을 추적하기 위해 대기열을 사용하기 때문입니다.

질문 5: BFS를 사용하면 어떤 이점이 있나요?

답변: BFS는 구현이 간단하고 비가중 그래프에서 최단 경로를 찾는 데 효율적입니다. 또한 그래프의 모든 꼭지점을 방문하도록 보장합니다.

관련 기사:

  • BFS에 관한 최근 기사
  • 깊이 우선 순회
  • 너비 우선 탐색의 응용
  • 깊이우선탐색의 응용
  • 너비 우선 탐색(BFS)의 시간 및 공간 복잡도