본문 바로가기
알고리즘 정리

그래프 탐색하기 위한 대표적인 알고리즘 DFS/BFS - 사전 단계 (스택,큐,재귀함수 이해)

by 조조링 2025. 2. 10.
728x90
반응형

 

1. 탐색 (Search)

탐색은 많은 양의 데이터 중에서 원하는 데이터를 찾는 과정을 의미한다. 

대표적인 탐색 알고리즘으로 DFS(Depth First Search)와 BFS(Breadth First Search)가 있으며, 이를 이해하려면 스택(Stack)과 큐(Queue) 자료구조를 먼저 알아야 한다.


 

2. 스택 (Stack)

스택은 접시 쌓기에 비유할 수 있다. 

- 접시를 아래에서 위로 차곡차곡 쌓고,

- 가장 위에 있는 접시부터 치워야 한다.

이 구조를 선입후출(First In Last Out, FILO) 구조라고 한다. 

# 스택 구현 예제
stack = []

# 삽입(5)-삽입(2)-삽입(3)-삽입(7)-삭제()-삽입(1)-삭제()
stack.append(5)
stack.append(2)
stack.append(3)
stack.append(7)
stack.pop() # 가장 마지막에 삽입된 7 삭제
stack.append(1)
stack.pop() # 가장 마지막에 삽입된 1 삭제

print(stack)  # 출력: [5, 2, 3]

 

파이썬에서 스택 이용할 때에는 별도의 라이브러리를 사용할 필요가 없다. 

기본 리스트에서 append()와 pop() 메서드를 이용하면 스택 자료구조와 동일하게 동작한다.


3. 큐 (Queue)

큐는 대기 줄에 비유할 수 있다. 

- 줄을 서는 순서대로 입장하며, 먼저 온 사람이 먼저 나간다.

이 구조를 선입선출(First In First Out, FIFO) 구조라고 한다.

# 큐 구현 예제
from collections import deque

# 큐(Queue) 구현을 위해 deque 라이브러리 사용
queue = deque()

# 삽입(5)-삽입(2)-삽입(3)-삽입(7)-삭제()-삽입(1)-삭제()
queue.append(5)
queue.append(2)
queue.append(3)
queue.append(7)
queue.popleft() # 가장 먼저 삽입된 5 삭제
queue.append(1)
queue.popleft() # 그 다음으로 삽입된 2 삭제

print(queue) # 출력: deque([3, 7, 1])

 

파이썬에서 큐를 구현할 때는 collections 모듈에서 제공하는 deque 자료구조를 활용한다.

deque의 장점은 스택과 큐의 장점을 모두 채택한 자료구조로, 삽입과 삭제가 리스트보다 효율적이다.

 


4. 재귀 함수 (Recuesive Function)

재귀 함수란 자기 자신을 다시 호출하는 함수이다.

재귀 함수를 사용할 때는 반드시 종료 조건을 명시해야 한다. 

# 재귀 함수 종료 예제
def recursive_function(i):
    # 종료 조건
    if i == 3:
        return
    print(i,'번째 재귀 함수에서',i+1,'번째 재귀 함수를 호출합니다.')
    recursive_function(i+1)
    print(i,'번째 재귀 함수를 종료합니다.')
    
recursive_function(1)

# 1 번째 재귀 함수에서 2 번째 재귀 함수를 호출합니다.
# 2 번째 재귀 함수에서 3 번째 재귀 함수를 호출합니다.
# 2 번째 재귀 함수를 종료합니다.
# 1 번째 재귀 함수를 종료합니다.

 

재귀 함수가 수행될 때, 가장 마지막에 호출된 함수가 먼저 종료된다. 이는 컴퓨터 내부에서 재귀 함수가 스택 자료구조를 이용하기 때문이다.


5. 재귀 함수와 반복문을 활용한 팩토리얼 문제

팩토리얼(Factorial)은 자연수 n에 대해 1부터 n까지의 모든 수의 곱을 의미한다.

수학적으로 팩토리얼을 점화식으로 표현하면 다음과 같다.

1. 종료 조건: n이 0 또는 1일 때, factorial(n) = 1

2. 점화식: factorial(n) = n * factorial(n - 1)

# 반복적으로 구현한 n!
def factorial_iterative(n):
    result = 1
    
    for i in range(1,n+1):
        result *= i
    return result
# 재귀적으로 구현한 n!
def factorial_iterative(n):
    if n <= 1:
        return 1
    return n*factorial_iterative(n-1)

 

재귀 구현의 장점은?

재귀 함수의 가장 큰 장점은 수학의 점화식을 그대로 코드로 옮길 수 있다는 점이다.

점화식은 특정 함수가 자신보다 작은 변수에 대한 함수와의 관계로 표현된 수학적 식이다.

 

(이 개념은 이후 다이나믹 프로그래밍(Dynamic Programming)에서 중요한 역할을 한다.)

 

 

참고 자료 

[1] 이것이 취업을 위한 코딩 테스트다 with 파이썬 (나동빈, 한빛미디어)

728x90
반응형

댓글