Moe's Tech Blog
[알고리즘] 재귀함수에 관하여 본문
- DFS 와 BFS를 구현하려면 재귀 함수의 이해가 필요
- 영어로는 recursive function이라고 한다
- 재귀함수란 자기 자신을 다시 호출하는 함수를 의미
function recursiveFunction() {
console.log("This is a recursive function");
return recursiveFunction();
}
- 재귀함수 종료 조건이 없으면 다음의 에러가 나타난다
Maximum call stack size exceeded
- 재귀함수는 stack 자료구조를 이용한다
- 가장 마지막에 호출한 함수가 끝나야 그 앞의 호출이 종료된다
재귀 함수 종료 조건
- 재귀함수를 사용할때는 종료 조건이 꼭 필요
- 종료 조건이 없으면 에러 뜰때까지 무한 호출
- 종료할때 if 문 안에 return을 사용한다
function recursiveFunction(i) {
console.log(`on ${i}th step`);
if (i === 10) return;
recursiveFunction(i+1);
}
재귀 함수 장점
- 코드가 간결해진다
재귀 함수 단점
- Stack 자료구조를 사용하므로 메모리 과도화에 취약하다
비재귀 함수 장점
- Maximum call stack exceeded 에러로부터 보다 자유로워진다
비재귀 함수 단점
- 코드가 읽기 어렵다
재귀 함수를 비재귀 함수로
- 유형 1 - 실제로 작업하는 부분이 앞에 있는 경우
recursive(인자 리스트)
{
if (종료 조건)
{
종료 처리
}
else
{
process(인자 리스트)
recursive(변경된 인자 1)
recursive(변경된 인자 2)
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
를 다음으로 변경:
non_recursive(인자 리스트)
{
/* 스택의 초기화 */
init_stack()
push(인자 리스트)
/* 스택이 비면 끝 */
while(!is_stack_empty())
{
인자 리스트 = pop()
if(!종료 조건)
{
process(인자 리스트)
push(변경된 인자 1)
push(변경된 인자 2)
}
/* 종료 조건이면 */
else
{
종료 처리
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
- 유형 2 - 실제로 작업하는 부분이 중간에 있는 경우
recursive(인자 리스트)
{
지역 변수들
if (종료 조건)
{
종료 처리
}
else
{
recursive(변경된 인자 1)
process(인자 리스트)
recursive(변경된 인자 2)
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
를 다음으로 변경:
non_recursive(인자 리스트)
{
/* 작업을 완료 했은지를 확인하기 위한 Flag */
let done = false;
/* 스택의 초기화 */
init_stack()
while(!done)
{
while(!종료 조건)
{
push(인자 리스트)
인자 리스트 = 변화된 인자 1
}
종료 처리
if(!is_stack_empty())
{
인자 리스트 = pop()
process(인자 리스트)
인자 리스트 = 변화된 인자 2
}
else
{
done = true
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
- 유형 3 - 실제로 작업하는 부분이 아래에 있는 경우
recursive(인자 리스트)
{
지역 변수들
if (종료 조건)
{
종료 처리
}
else
{
recursive(변경된 인자 1)
recursive(변경된 인자 2)
process(인자 리스트)
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
를 다음으로 변경:
non_recursive(인자 리스트)
{
/* 작업을 완료 했은지를 확인하기 위한 Flag */
let done = false;
/* 무한 루프를 방지하기 위한 방책 */
인자 리스트의 복사본
/* 스택의 초기화 */
init_stack()
while(!done)
{
while(!종료 조건)
{
push(인자 리스트)
인자 리스트 = 변화된 인자 1
}
종료 처리
if(!is_stack_empty())
{
인자 리스트 복사본 = 인자 리스트
인자 리스트 = pop()
if (인자 2로의 변화가 종료 조건이 아니면)
{
if(인자 2로의 변화 == 인자 리스트의 복사본)
{
process(인자 리스트)
}
else
{
push(인자 리스트)
인자 리스트 = 변화된 인자 2
break
}
}
}
else
{
process(인자 리스트)
}
if(is_stack_empty)
{
done = true
}
}
출처: https://steadyandslow.tistory.com/117 [더디지만... 꾸준히...]
참고
- 재귀 호출 - 재귀 함수를 비재귀 함수로, 더디지만... 꾸준히...: https://steadyandslow.tistory.com/11
- 이것이 취업을 위한 코딩 테스트다 with 파이썬, 나동빈: https://books.google.ca/books?id=vBz-DwAAQBAJ&source=gbs_book_other_versions
'Algorithms > Notes' 카테고리의 다른 글
[Algorithm] 7 Steps to construct algorithm solution (0) | 2022.06.20 |
---|---|
[알고리즘] 그리디 알고리즘에 관하여 (0) | 2022.04.18 |
[알고리즘] 계수 정렬에 관하여 (0) | 2022.04.17 |
[알고리즘] 퀵 정렬에 관하여 (0) | 2022.04.16 |
[알고리즘] 삽입 정렬에 관하여 (0) | 2022.04.16 |