해당 글에서는 재귀함수에 대해 이해하며 다양한 예시와 재귀함수를 이용한 알고리즘을 기반으로 이해를 돕기 위해 작성한 글입니다.
1) 재귀함수(Recursion Function)
💡 재귀함수(Recursion Function)란? - 함수 내부에서 ‘자기 자신을 호출’하는 함수를 의미합니다. 이를 통해서 함수가 자신을 반복적으로 호출하면서 원하는 결과를 도출할 수 있습니다.
- 단, 재귀함수를 사용하는 경우 함수 호출이 계속해서 쌓이기 때문에 호출 스택이 많아져서 성능이 저하될 수 있습니다. 따라서 재귀함수를 작성할 때는 무한루프에 빠지지 않도록 종료 조건을 명확하게 설정해주어야 합니다.
[ 더 알아보기 ] 💡 호출 스택(Call Stack)이란?
- 프로그램에서 함수나 메서드를 호출할 때 해당 함수나 메서드의 실행이 끝날 때까지 실행되는 다른 함수나 메서드의 호출 정보를 저장하는 자료구조입니다. - 이 스택은 함수가 호출될 때마다 그 함수의 호출 정보를 저장하고 함수의 실행 결과가 반환되면 해당 함수의 호출 정보를 스택에서 제거합니다. - 호출 스텍은 디버깅, 예외 처리 및 재귀 함수와 같은 다양한 프로그래밍 작업에 사용됩니다.
💡 재귀 함수와 재귀 알고리즘은 다른 것인가?
- 재귀 알고리즘은 문제를 해결하기 위해 재귀 함수를 사용하는 알고리즘을 의미합니다
2) 재귀 함수의 장단점
1. 장점
번호
장점
1
코드의 가독성이 높아집니다. 재귀적인 호출을 통해 코드를 간결하게 작성할 수 있습니다.
2
일부 알고리즘에서는 반복문을 사용하는 것보다 재귀 함수를 사용하는 것이 더 직관적입니다.
2. 단점
번호
단점
1
재귀 함수는 함수를 호출할 때마다 스택에 새로운 프레임을 생성합니다. 따라서, 스택이 너무 깊어질 경우에는 스택 오버플로우가 발생할 수 있습니다.
2
재귀 함수는 함수의 호출이 반복적으로 일어나기 때문에, 일반적으로 반복문을 사용하는 것보다 느립니다.
3) 재귀 함수의 활용한 예시
💡 재귀 함수를 이용하여 모듈을 구성하는 예시를 담고 있습니다.
1. 팩토리얼 계산 방법
💡 팩토리얼 이란?
- 자연수 n에 대해서 1부터 n까지의 모든 자연수를 곱한 값을 의미합니다.
💡 해당 기능은 factorial() 함수에 파라미터로 값을 넘길 경우 재귀함수로 반복하여 결괏값을 반환해 주는 함수입니다.
- 이진탐색은 배열의 중간값을 선택한 후, 찾고자 하는 데이터와 중간값을 비교합니다. 만약 중간값이 찾고자 하는 데이터보다 크다면, 중간값의 왼쪽 부분 배열에서 다시 중간값을 선택하여 비교합니다. 반대로 중간값이 찾고자 하는 데이터보다 작다면, 중간값의 오른쪽 부분 배열에서 다시 중간값을 선택하여 비교합니다. 이 과정을 반복하여 원하는 데이터를 찾습니다. - 이진탐색은 데이터의 개수가 많을 때도 빠르게 데이터를 찾을 수 있기 때문에 많이 사용되는 알고리즘 중 하나입니다.
💡 높은 인덱스가 낮은 인덱스보다 크거나 같은지 확인합니다.
1. 중간 값을 구합니다.
2. 배열의 요소 값이 찾는 값과 동일하면 중간 값을 반환합니다.
3. 중간 값이 키보다 큰 경우 : 낮은 인덱스와 중간 인덱스에서 1을 뺀 값을 가지고 함수를 재귀적으로 호출합니다.
4. 중간 값이 키보다 작은 경우 : 중간 인덱스에 1을 더하고 높은 인덱스와 함께 함수를 재귀적으로 호출합니다
/**
* 재귀를 사용하여 이진 알고리즘을 구현합니다.
* @param arr 배열
* @param low 낮은 인덱스
* @param high 높은 인덱스
* @param key 검색할 값
* @return
*/publicstaticintbinarySearch(int[] arr, int low, int high, int key){
// 1. 높은 인덱스가 낮은 인덱스보다 크거나 같은지 확인합니다.if (high >= low) {
// 2. 중간 값을 구합니다.int mid = low + (high - low) / 2;
// 3. 배열의 요소 값이 찾는 값과 동일하면 중간 값을 반환합니다.if (arr[mid] == key) {
return mid;
}
// 4. 중간 값이 키보다 큰 경우 : 낮은 인덱스와 중간 인덱스에서 1을 뺀 값을 가지고 함수를 재귀적으로 호출합니다.elseif (arr[mid] > key) {
return binarySearch(arr, low, mid - 1, key);
}
// 5. 중간 값이 키보다 작은 경우 : 중간 인덱스에 1을 더하고 높은 인덱스와 함께 함수를 재귀적으로 호출합니다else {
return binarySearch(arr, mid + 1, high, key);
}
}
// 6. 높은 인덱스가 낮은 인덱스보다 작으면 배열에서 키를 찾지 못했음을 나타내기 위해 -1을 반환합니다.return -1;
}