[Java] 재귀함수란?
재귀함수란?
재귀함수(Recursion)는 정의 단계에서 자신을 재참조하는 함수
를 의미한다.
함수 내에서 자기 자신을 호출하는 프로세스이다.
좀 더 쉽게 이해하기 위해 아래 나무위키의 예시를 보자.
재귀함수를 사용하여 HelloWorld 를 반복 출력해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PlusFunction {
public static void main(String[] args) {
HelloWorld(5); // 메서드 호출
}
public static void HelloWorld(int n)
{
// n이 0인 경우 return
if(n == 0)
return;
System.out.println("HelloWorld"); // HelloWorld 출력
HelloWorld(n-1);
}
}
위 코드에서 HelloWorld 메소드를 보자.
if문을 이용해 매개변수 n 의 값이 0이면 return; 을 이용해 메소드를 종료하고,
n 의 값이 0이 아니면 자기자신을 다시 호출하여 n-1 값을 매겨변수로 넘겨준다.
위와 같이 자기자신을 재참조하여 호출하는 프로세르를 재귀함수
라고 부른다.
반복문 vs 재귀함수
재귀함수를 반복문과 비교했을때 장단점은 아래와 같다.
반복문은 재귀함수에 비해 속도가 빠르지만, 코드가 복잡해 보일 수 있다.
재귀함수는 클린코드 작성이 가능하지만 메모리 사용이 많아 반복문에 비해 속도가 느리다.
지속적으로 함수를 호출하게 되면서 지역변수, 매개변수, 반환값을 모두 스택에 저장해야 하는데 이러한 과정은 변수의 값만 사용하는 반복문에 비해 메모리를 더 많이 사용하게 되고 결국 성능저하로 이어지게 된다.
비용 문제를 해결하기 위해 나온 방법이 꼬리재귀(tail call recursion) 이고 아래에서 설명하겠다.
꼬리재귀함수(tail call recursion)
재귀 함수의 문제점인 자기 자신을 호출 한 뒤 결과를 기다리며 생기는 메모리 낭비를 해결하기 위해 재귀 호출이 끝나는 시점에 아무 일도 하지 않고 바로 결과를 반환하도록 하는 방법으로 함수의 상태유지 및 추가 연산을 하지 않기에 스택 오버 플로우 해결이 가능
하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
System.out.println(factorial(13));
System.out.println(factorialTail(13, 1));
}
public static int factorial(int n){
return factorialTail(n, 1);
}
public static int factorialTail(int n, int acc){
if(n == 1) return acc;
return factorialTail(n - 1, acc * n);
}
차이점을 보면 return 할 때 재귀함수에서 필요한 매개변수를 모두 전달하여, 연산을 없앴고 이러한 사용법을 꼬리 재귀 함수라고 부른다.
Leave a comment