The Way

재귀함수(1): 재귀함수의 기본 본문

공부/컴퓨터 알고리즘

재귀함수(1): 재귀함수의 기본

Jeonggyun 2017. 8. 24. 19:45

1. 재귀함수란?

재귀함수란 함수 내에서 같은 함수(자기 자신)가 또 실행되는 함수의 형태를 말한다.

가장 기본적인 형태는 base case와 recursive case 둘을 갖는 형태인데, 가장 유명한 예시인 팩토리얼 구하기를 살펴보자.


int fac1(int n) {
	// base case
	if (n <= 1) return 1;

	// recursive case
	return n * fac1(n - 1);
}

(편의상 음수일 때는 무시하자)


이렇게 쉬울 수도 없다. n이 1이하일 때는 1을 그대로 반환하고 2 이상이이면 n * (n-1)!을 반환한다.

사실 이 예시는 굳이 재귀함수를 이용할 필요는 없다. 이렇게 해도 같은 결과를 반환한다.

int fac2(int n) {
	int p = 1;
	for (int i = 2; i <= n; ++i) p *= i;

	return p;
}


심지어 속도도 후자가 더 빠르다.

재귀함수를 사용하면 함수를 계속 호출해야되기 때문에 매개변수에 따른 스택이 쌓이고, 결과값을 전달하고 하는 과정이 있기 때문에 훨씬 느릴 수밖에 없다.


비교를 위해 int가 허용하는 범위에서 최대치인 13! (=1932053504)를 1000만번씩 구하며 그 시간을 비교해보았다.


당연하게도 재귀함수를 사용하지 않은 쪽이 6배 정도 더 빨랐다.

그리고 사실, 모든 코드는 재귀함수를 사용하지 않아도 작성할 수 있다.

그렇다면 우리는 왜 더 느린 재귀함수를 써야 할까?



2. 재귀함수의 필요성

재귀함수의 존재 가치는 크게 두 가지에 있다고 생각한다.


(1) 코드가 간결해진다

재귀함수를 사용하면 코드의 길이를 크게 줄일 수 있다. 컴퓨팅 파워가 많이 증가하고 있는 현재 시점에서, 이는 대단한 장점이 아닐 수 없다.


(2) 코드가 직관적으로 변한다

재귀함수를 사용하면 전체 코드의 흐름을 보다 직관적으로 파악할 수 있다.

프로그래밍을 하는 사람이라면 전체 코드의 흐름은 파악하고 있어야 한다. 이 때 재귀함수는 코드의 흐름을 파악하는 데에 큰 도움을 줄 수 있다.


간단한 예시를 통해 살펴보자.

여기 아주 간단한 형태의 점화식이 있다.

$a_0 = 1, \; a_n = 3a_{n-1} + 2$


이 점화식의 n번째 항을 구하기 위한 코드를 작성해보자.


i) 재귀함수를 사용하지 않았을 때

int rec1(int n) {
	int p = 1;
	for (int i = 0; i < n; ++i) {
		p *= 3;
		p += 2;
	}
	return p;
}


ii) 재귀함수를 사용했을 때

int rec2(int n) {
	if (n == 0) return 1;
	return 3 * rec2(n - 1) + 2;
}


길이도 길이지만, 코드가 한눈에 봐도 훨씬 더 직관적이라는 것을 알 수 있다.


사실 이 예시는 그렇게 복잡하지 않으므로, 재귀함수의 필요성이 잘 와닿지 않을 수도 있다.

나같아도 이 정도 차이면 재귀함수를 사용하지 않고, 더 빠른 속도를 선택할 것 같다.


다음 글부터는 보다 복잡한 예제들을 풀어볼 것인데, 그 과정에서 재귀함수의 가치를 느낄 수 있길 바란다.

'공부 > 컴퓨터 알고리즘' 카테고리의 다른 글

마스터 정리  (0) 2017.10.30
거듭제곱(나머지) 계산하기  (1) 2017.10.23
Big-O(빅 오) 표기법: 점근 표기법  (0) 2017.10.20
재귀함수(3): 조합  (0) 2017.08.28
재귀함수(2): 피보나치 수열 구하기  (0) 2017.08.24
Comments