2월 23일 - 재귀 함수

Yullgiii·2024년 2월 23일
0
post-thumbnail

재귀 함수와 최적화

재귀 함수는 자기 자신을 호출하는 함수로, 문제를 더 작은 문제로 분할하여 해결하는 분할 정복 전략에 기반한다. 이 방식은 데이터 구조 탐색, 알고리즘 문제 해결 등 다양한 분야에서 활용된다.

재귀 함수의 동작 원리와 Call Stack

재귀 함수가 실행될 때, 함수의 호출 정보는 Call Stack에 저장된다. Call Stack은 함수 호출 시 해당 함수의 매개변수, 지역 변수, 반환 주소를 저장하는 스택 자료구조이다. 재귀 함수의 실행 과정은 다음과 같다:

  1. Base Case: 재귀 호출을 중단하고 결과를 반환하는 조건. 이 조건 없이 재귀 함수를 계속 호출하면 스택 오버플로우가 발생할 수 있다.
  2. Recursive Case: 함수가 자기 자신을 호출하는 과정으로, 문제의 크기를 점점 줄여 나간다.

예를 들어, factorial(n) 함수는 n * factorial(n-1)을 호출하며, factorial(1)이 base case가 된다. 이 과정에서 Call Stack에는 factorial(n), factorial(n-1), ..., factorial(1)의 정보가 차례로 쌓이고, 각 함수의 실행이 완료되면 결과를 반환하며 Call Stack에서 제거된다.

재귀 함수의 최적화: 꼬리 호출 최적화(Tail Call Optimization, TCO)

꼬리 호출 최적화는 함수의 반환값이 또 다른 함수 호출일 때, 새로운 스택 프레임을 생성하지 않고 기존의 스택 프레임을 재사용하여 재귀 함수를 최적화하는 방법이다. 이 최적화는 다음과 같은 조건에서 가능하다:

  • 재귀 호출이 함수의 마지막 동작이다.
  • 재귀 호출 결과에 추가 연산을 수행하지 않는다.
  • 재귀 함수의 상태를 매개변수로 전달한다.

예시: 꼬리 재귀 최적화를 적용한 피보나치 수열 계산

def fibonacci(n, a=0, b=1):
    if n == 0:
        return a
    if n == 1:
        return b
    return fibonacci(n-1, b, a+b)

이 함수는 마지막에 자신을 호출하고, 추가 연산 없이 결과를 반환하기 때문에 꼬리 호출 최적화가 가능하다. 최적화를 지원하는 언어에서는 Call Stack을 재사용하여 큰 n 값에 대해서도 스택 오버플로 없이 함수를 실행할 수 있다.

언어별 최적화 지원

모든 프로그래밍 언어가 꼬리 호출 최적화를 지원하는 것은 아니다. 예를 들어, Python과 Java는 기본적으로 TCO를 지원하지 않는 반면, Scala와 Erlang은 이를 지원한다. 재귀 함수를 사용할 때는 해당 언어의 스펙을 확인하고, 필요에 따라 재귀 대신 반복문으로 로직을 변경하는 등 최적화를 고려해야 한다.

profile
개발이란 무엇인가..를 공부하는 거북이의 성장일기 🐢

0개의 댓글