C# - BFS (너비 우선 탐색) / DFS (깊이 우선 탐색)

2025. 9. 25. 22:33·C#

자료구조는 크게 두 가지로 나뉜다.

 

  • 선형 구조: 데이터가 일렬로 이어지는 구조. 예를 들어 배열, 리스트, 큐, 스택 등이 있다. 한 원소 다음에 또 다른 원소가 순차적으로 이어진다.
  • 비선형 구조: 데이터가 계층적 혹은 망 형태로 이어진 구조. 트리(Tree), 그래프(Graph) 등이 대표적이다. 한 노드에서 여러 갈래로 뻗어 나가며, 선형 구조보다 더 복잡한 관계를 표현할 수 있다.

 

이번 글에서는 비선형 구조의 BFS, DFS에 대해 이야기해 볼 것이다.

 


BFS : Breadth First Search ( 너비 우선 탐색 )

BFS는 가까운 곳부터 차례대로 탐색하는 방법이다.

시작 노드에서 출발해 인접한 노드들을 먼저 탐색하고, 그 다음 단계로 더 멀리 있는 노드들을 탐색한다.

그렇기 때문에 최단 경로 탐색에 유리하지만 메모리를 많이 사용한다는 단점이 있다.

RTS 게임에서의 최단 경로 계산 같은 경우에 사용하기 좋다.

 

 

BFS의 진행 순서를 표현한 그림이다.

A → B → C → D → E → F → G

이런 식으로 가장 가까운 노드를 먼저 탐색한 뒤,

그 다음 그 노드들과 연결돼있는 노드들을 탐색하는 방식이다.

 

BFS는 큐(Queue)를 사용해 구현할 수 있다.

 

예시 코드

public void BFS(Node<T> start, Node<T> target)
{
    Queue<Node<T>> queue = new Queue<Node<T>>(); // 임시로 큐 생성
    List<Node<T>> visited = new List<Node<T>>(); // 방문 기록을 List로 관리

    queue.Enqueue(start);
    while (queue.Count > 0)
    {
        Node<T> current = queue.Dequeue();

        if(visited.Contains(current))
        {
            continue;
        }

        Console.WriteLine($"지하철 역 방문: {current.Value}"); // 방문역 출력
        visited.Add(current); // 방문했다고 기록

        if (current.Equals(target))
        {
            Console.WriteLine($"목표 역 {target.Value} 발견!");
            return;
        }

        foreach (var neighbor in current.Neighbors)
        {
            if(visited.Contains(neighbor) == false) // 이미 방문한 노드는 방문 예정 큐에 넣지 않음
            {
                queue.Enqueue(neighbo);
            }
        }

    }
    Console.WriteLine("경로 탐색 실패");
}

 

 

 


DFS : Depth First Search ( 깊이 우선 탐색 )

DFS는 이름 그대로 깊게 타고드는 탐색 방법이다.

시작 노드에서 출발해 한 갈래를 끝까지 탐색하며, 더 이상 진행할 수 없을 때 이전 분기점으로 돌아가 다른 갈래를 탐색한다.

모든 경로를 끝까지 확인해야 하는 경우에 적합하며 메모리 사용량이 BFS 보다 적다.

하지만 최단 경로를 보장하지 못한다고 한다.

 

 

 

DFS의 진행 순서를 표현한 그림이다.
A → B → D → E → C → F → G
이런 식으로 한 쪽 라인을 전부 탐색하고, 이전 분기 노드를 다시 끝까지 탐색하고를 반복하는 방식이다.

그런데 여기서...

이 두 진행 순서를 봤을때 D처럼 좌측 끝에 탐색 목표가 있는 경우, 탐색 속도가 더 빠를 수도 있는 거 아닌가?

라는 의문이 들었다.

A B D vs A B C D 인데 메모리를 더 많이 쓴다?
당연히 A B D 가 빠를 것이다.
하지만 비선형 자료 구조는 노드의 연결이 꼭 하나만 있다는 법이 없다.
즉 A B D 로 D로의 경로를 찾았으나, 다시 뒤에서 검색해보니 A에서 D로 바로 접근할 수 있는 최단 경로가 따로 있을 수 있다.

즉 전체를 순회하기 전에는 DFS로 구한 경로가 최단 경로 라는 보장을 받지 못하기 때문에, 결국 최단 경로를 알기 위해서는 전부 순회해야만 하는 것이나 다름 없기 때문에 최단경로 검색에 BFS가 더 적합하다는 이야기다.


DFS는 스택(Stack)이나 재귀함수를 이용해 구현할 수 있다.

 

 

예시 코드

public void DFS(Node<T> start, Node<T> target)
{
    Stack<Node<T>> stack = new Stack<Node<T>>(); // 임시로 큐 생성
    List<Node<T>> visited = new List<Node<T>>(); // 방문 기록을 List로 관리

    stack.Push(start);
    while (stack.Count > 0)
    {
        Node<T> current = stack.Pop();

        if(visited.Contains(current))
        {
            continue;
        }

        Console.WriteLine($"지하철 역 방문: {current.Value}"); // 방문역 출력
        visited.Add(current); // 방문했다고 기록

        if (current.Equals(target))
        {
            Console.WriteLine($"목표 역 {target.Value} 발견!");
            return;
        }

        foreach (var neighbor in current.Neighbors)
        {
            if(visited.Contains(neighbor) == false) // 이미 방문한 노드는 방문 예정 큐에 넣지 않음
            {
                stack.Push(neighbor);
            }
        }

    }
    Console.WriteLine("경로 탐색 실패");
}

 

 

 

재귀 함수를 이용해서 이렇게 구성해 볼 수도 있다.

 

public void DFS(Node<T> current, Node<T> target, HashSet<Node<T>> visited)
{
    if (current == null) return;

    // 이미 방문했다면 중복 방지
    if (visited.Contains(current)) return;

    // 현재 노드 방문
    Console.WriteLine($"지하철 역 방문: {current.Value}");
    visited.Add(current);

    // 목표 노드 도착 확인
    if (current.Equals(target))
    {
        Console.WriteLine($"목표 역 {target.Value} 발견!");
        return;
    }

    // 이웃 노드 재귀 호출
    foreach (var neighbor in current.Neighbors)
    {
        DFS(neighbor.To, target, visited);
    }
}

 


 

정리

  BFS DFS
구현 방식 큐 스택 / 재귀
탐색 순서 가까운 노드부터 하나의 줄기 끝까지 간 다음 순회
장점 최단 경로 보장 메모리 적게 사용
단점 메모리 사용량 많 최단 경로 보장 X
게임 활용 최단 경로 탐색, 길 찾기 던전 탐험, 숨겨진 아이템 찾기

 

 

 

BFS와 DFS의 차이

  • BFS는 큐를 사용해 가까운 노드부터 탐색, 최단 경로 보장.
  • DFS는 스택/재귀를 사용해 깊이 들어감, 최단 경로 보장 불가.
  • 보장 불가라는 말은, 운 좋게 짧은 경로를 먼저 찾을 수도 있지만(이 자체만으로도 보장성이 아님), 그것을 최단 경로라 보장하지는 못하기 때문에 최단 경로 탐색이라고는 할 수 없다.

 

BFS, DFS 사용처

  • BFS: 최단 거리 필요, 길찾기, 네트워크 최단 전송 경로.
  • DFS: 모든 경로 탐색, 미로/던전 탐험, 조합/백트래킹 문제.

 

시간복잡도와 공간복잡도

  • 그래프의 정점 개수 V, 간선 개수 E라 할 때,
    • BFS: O(V+E)
    • DFS: O(V+E)
  • 시간복잡도는 동일하지만, BFS는 큐에 많은 노드를 보관해야 하므로 공간복잡도가 커질 수 있다.

'C#' 카테고리의 다른 글

C# - 딕셔너리 (Dictionary)  (0) 2025.09.26
C# - 스택 (Stack), 큐 (Queue)  (0) 2025.09.26
C# - 자료구조 실습 - 인벤토리  (0) 2025.09.25
C# - 자료구조 : Indexer, List, LinkedList  (0) 2025.09.24
C# - record  (0) 2025.09.23
'C#' 카테고리의 다른 글
  • C# - 딕셔너리 (Dictionary)
  • C# - 스택 (Stack), 큐 (Queue)
  • C# - 자료구조 실습 - 인벤토리
  • C# - 자료구조 : Indexer, List, LinkedList
ellug
ellug
Web / App / Game Dev
  • ellug
    dev.ellug
    ellug
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • Javascript (React, Next) (1)
      • C# (66)
      • Graphics (1)
      • Unity (25)
      • 프로그래머스 (0)
        • Lv.0 (0)
        • Lv.1 (0)
        • Lv.2 (0)
        • Lv.3 (0)
      • AI Agent (0)
      • StableDiffusion (0)
      • ETC (1)
      • 잡담 (0)
      • 유머 (0)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    큐
    delegate
    Network
    Abstract
    struct
    알고리즘
    C#
    콘솔
    Photon
    네트워크
    firebase
    function
    list
    유니티
    스택
    최적화
    stack
    Design Pattern
    unity
    inputsystem
    터미널
    interface
    게임
    class
    useState
    추상 클래스
    console
    클래스
    자료구조
    Queue
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
ellug
C# - BFS (너비 우선 탐색) / DFS (깊이 우선 탐색)
상단으로

티스토리툴바