넓우선탐색(Breadth-First Search, BFS)란?
- 넓이 우선 탐색(Breadth-First Search, BFS)은 그래프 탐색 알고리즘 중 하나로, 루트 노드에서 시작해서 인접한 노드를 먼저 모두 탐색한 후에, 그 인접한 노드들을 시작점으로 다시 인접한 노드를 모두 방문하는 방법이다.
BFS의 원리
BFS는 큐(Queue) 자료구조를 이용하여 구현할 수 있다. 큐에 먼저 시작 노드를 넣고, 해당 노드와 인접한 모든 노드들을 큐에 추가한다. 그리고 큐에서 하나씩 노드를 빼서 그 노드와 인접한 노드들을 다시 큐에 추가한다. 이 과정을 큐가 빌 때까지 반복하면 된다. 큐를 이용하기 때문에 먼저 들어온 것이 먼저 처리되기 때문에 넓이 우선 탐색이라고 부른다.
BFS는 최단 경로 탐색 등에 자주 사용됩니다. 또한, 미로 찾기와 같은 문제에서도 사용할 수 있습니다. 단점으로는 BFS는 깊이 우선 탐색(DFS)에 비해 탐색하는 노드의 수가 많아지기 때문에, 탐색 속도가 느리다는 점이 있습니다.
넓이 우선 탐색(BFS)
- C언어
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct tagNode
{
ElementType Data;
} Node;
typedef struct tagCircularQueue
{
int Capacity;
int Front;
int Rear;
Node* Nodes;
} CircularQueue;
void CQ_CreateQueue(CircularQueue** Queue, int Capacity);
void CQ_DestroyQueue(CircularQueue* Queue);
void CQ_Enqueue(CircularQueue* Queue, ElementType Data);
ElementType CQ_Dequeue(CircularQueue* Queue);
int CQ_GetSize(CircularQueue* Queue);
int CQ_IsEmpty(CircularQueue* Queue);
int CQ_IsFull(CircularQueue* Queue);
int CQ_Front(CircularQueue* Queue);
int CQ_Back(CircularQueue* Queue);
void CQ_CreateQueue(CircularQueue** Queue, int Capacity)
{
// 큐를 자유 저장소에 생성
(*Queue) = (CircularQueue*)malloc(sizeof(CircularQueue));
// 입력된 Capacity+1 만큼의 노드를 자유 저장소에 생성
(*Queue)->Nodes = (Node*)malloc(sizeof(Node) * (Capacity + 1));
(*Queue)->Capacity = Capacity;
(*Queue)->Front = 0;
(*Queue)->Rear = 0;
}
void CQ_DestroyQueue(CircularQueue* Queue)
{
free(Queue->Nodes);
free(Queue);
}
void CQ_Enqueue(CircularQueue* Queue, ElementType Data)
{
int Position = 0;
if (Queue->Rear == Queue->Capacity)
{
Position = Queue->Rear;
Queue->Rear = 0;
}
else
Position = Queue->Rear++;
Queue->Nodes[Position].Data = Data;
}
ElementType CQ_Dequeue(CircularQueue* Queue)
{
int Position = Queue->Front;
if (Queue->Front == Queue->Capacity)
Queue->Front = 0;
else
Queue->Front++;
return Queue->Nodes[Position].Data;
}
int CQ_GetSize(CircularQueue* Queue)
{
if (Queue->Front <= Queue->Rear)
return Queue->Rear - Queue->Front;
else
return Queue->Rear + (Queue->Capacity - Queue->Front) + 1;
}
int CQ_IsEmpty(CircularQueue* Queue)
{
return (Queue->Front == Queue->Rear);
}
int CQ_IsFull(CircularQueue* Queue)
{
if (Queue->Front < Queue->Rear)
return (Queue->Rear - Queue->Front) == Queue->Capacity;
else
return (Queue->Rear + 1) == Queue->Front;
}
int CQ_Front(CircularQueue* Queue)
{
return Queue->Nodes[Queue->Front].Data;
}
int CQ_Back(CircularQueue* Queue)
{
return Queue->Nodes[Queue->Rear - 1].Data;
}
int n = 5;
int visited[100];
int list[100][100];
void bfs(int v) {
CircularQueue* queue = NULL;
CQ_CreateQueue(&queue, 5);
CQ_Enqueue(queue,v);
visited[v] = true;
printf("%d\n", v);
while (CQ_IsEmpty(queue)) {
int temp = CQ_Dequeue(queue);
for (int i = n-1; i >= 0; i--) {
if (list[temp][i] && !visited[i]) {
CQ_Enqueue(queue, i);
printf("%d\n", i);
}
}
}
}
int main(void) {
n = 5;
list[0][1] = 1;
list[0][2] = 1;
list[1][0] = 1;
list[1][2] = 1;
list[1][3] = 1;
list[1][4] = 1;
list[2][0] = 1;
list[2][1] = 1;
list[3][1] = 1;
list[4][1] = 1;
//노드 방문
for (int i = 0; i < n; i++) {
if (!visited[i]) {
bfs(i);
}
}
}
- C#
using System;
using System.Collections.Generic;
namespace yongyong2
{
internal class Program
{
static int N;
static int[,] Map;
static bool[] dfsbool;
static bool[] bfsbool;
static void Main(string[] args)
{
string[] input1 = Console.ReadLine().Split();
N = int.Parse(input1[0]);
int M = int.Parse(input1[1]);
int V = int.Parse(input1[2]);
Map = new int[N + 1, N + 1];
bfsbool = new bool[N + 1];
for (int i = 0; i < M; i++)
{
string[] input2 = Console.ReadLine().Split();
int temps = int.Parse(input2[0]);
int tempe = int.Parse(input2[1]);
Map[temps, tempe] = 1;
Map[tempe, temps] = 1;
}
BFS(N, V);
}
public static void BFS(int N, int V)
{
Queue<int> queue = new Queue<int>();
queue.Enqueue(V);
bfsbool[V] = true;
Console.Write(V + " ");
while (queue.Count > 0)
{
int temp = queue.Dequeue();
for (int i = 1; i < N + 1; i++)
{
if (Map[temp, i] == 1 && bfsbool[i] == false)
{
queue.Enqueue(i);
Console.Write(i + " ");
bfsbool[i] = true;
}
}
}
}
}
}
예제 문제
[C#]백준 1260번: DFS와 BFS
https://www.acmicpc.net/problem/1260 1260번: DFS와 BFS 첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는
yongyongyee.tistory.com
[C#]백준 24444번: 알고리즘 수업 - 넓이 우선 탐색 1
https://www.acmicpc.net/problem/24444 24444번: 알고리즘 수업 - 너비 우선 탐색 1 첫째 줄에 정점의 수 N (5 ≤ N ≤ 100,000), 간선의 수 M (1 ≤ M ≤ 200,000), 시작 정점 R (1 ≤ R ≤ N)이 주어진다. 다음 M개 줄에 간
yongyongyee.tistory.com
'공부 > 알고리즘' 카테고리의 다른 글
[알고리즘]KMP 알고리즘 (0) | 2023.03.11 |
---|---|
[알고리즘] 깊이 우선 탐색(DFS) (0) | 2023.03.05 |
[알고리즘] 에라토스테네스의 체 (0) | 2023.02.02 |