일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- REST HTTP API
- 배열 탐색
- O(log n)
- root passwd
- Java
- git workflow
- N:N
- 코드스테이츠
- git 설정
- JAVA 재귀함수
- 자료구조
- 탐욕 알고리즘
- Spring
- 리눅스 사용권한
- http 응답코드
- 스키마 설계
- set-version
- mapstruct
- Spring 예외처리
- 스키마 디자인
- custom exception
- char to int
- ubuntu 패스워드
- file i/o
- 함수형 인터페이스
- Spring MVC
- RestControllerAdvice
- ubuntu
- ubuntu passwd
- AOP
Archives
- Today
- Total
개발소설
[JAVA] 재귀함수(Recursion) 본문
재귀함수 (Recursion)
- 재귀의 사전적 의미 : 원래의 자리로 되돌아가거나 되돌아옴
- 자기 자신을 호출하는 함수
- 반복적인 작업을 간결하게 해결 할 수 있다.
// 재귀함수 예제
class Recursion{
void recursion(){
System.out.println("제발 그만해..");
recursion();
}
}
// recursion() 호출시
/*
제발 그만해..
제발 그만해..
제발 그만해..
제발 그만해..
제발 그만해..
제발 그만해..
제발 그만해..
제발 그만해..
..
*/
재귀 함수의 장점
- 여러개의 반복문을 사용하지 않아, 코드가 간결, 수정이 용이해진다.
- 변수를 여러개 사용 할 필요가 없다.
재귀 함수의 단점
- 반복문과 달리, 코드의 흐름 직관적 파악이 안된다. (선언형 프로그래밍)
- 반복하여 메서드를 호출하여 지역변수, 매개변수, 반환값을 process stack의 저장
- 반복문보다 메모리를 더 많이 사용
- 메서드를 종료된 이후에 복귀를 위한 컨텍스트 스위칭* 비용 발생
재귀 함수를 사용하기 위한 조건
- 문제의 크기를 점점 작은 단위로 쪼갤 수 있다.
- 재귀 호출이 종료되는 시점이 존재해야 한다.
재귀 함수의 템플릿
public type recursive(input1, input2, ...) {
// Base Case : 문제를 더 이상 쪼갤 수 없는 경우
// 종료 조건
if (문제를 더 이상 쪼갤 수 없을 경우) {
return 단순한 문제의 해답;
}
// recursive Case
// 그렇지 않은 경우
// 문제의 정의
return 더 작은 문제로 새롭게 정의된 문제
// 예1. someValue + recursive(input1Changed, input2Changed, ...)
// 예2. someValue * recursive(input1Changed, input2Changed, ...)
}
예제1 1부터 num 까지의합
5 -> 1+2+3+4+5 = 15
public class Recursion {
public int sumTo(int num){
// 종료조건, num이 0되면 종료
if (num == 0) {
return 0;
}
// 문제 정의
return num + sumTo(num - 1);
// num값에 num-1값을 재귀함수로 호출하여 더한다.
}
}
- 5 + ( 4 + 3 + 2 + 1) -> 4 + (3 + 2 + 1) -> 3 + (2+1) -> 2 +(1) -> 1+(0) -> 종료 조건
- 리턴은 역순 (1) + 0 -> (2) + 1(1+0) -> (3) + 3(2+1) -> (4) + 6(3+2+1) -> (5) + 10(4+3+2+1) -> 15 (5+4+3+2+1)
예제2. 피보나치(fibonnacci) 수열
// 피보나치 수열의 num번째항 구하기
public class Recursion {
public int fibonacci(int num){
//TODO..
// 종료조건
if(num == 0) return 0; // 피보나치의 수열 첫번째항
if(num == 1) return 1; // 피보나치의 수열 두번째항
// 두항은 항상 고정된다.
// 문제의 정의
return fibonacci(num-1) + fibonacci(num-2); // 피보나치 수열의 현재 값은 앞에 두항의 덧셈이다.
// 1 = 1 + 0
// 2 = 1 + 1
// 3 = 2 + 1
// 5 = 3 + 2
// 8 = 5 + 3
}
}
예제3. 배열의 순서를 뒤집어서 리턴
ex. { 1 ,2, 3, 4 } -> { 4, 3, 2, 1}
public class Recursion {
public int[] reverseArr(int[] arr){
// 종료 조건
if(arr.length == 0) return arr; // 빈 배열인 경우 빈배열 그대로 리턴
// 문제 정의
int tail = arr[0]; // 맨앞 숫자가 맨뒤로 간다.
int[] head = reverseArr(Arrays.copyOfRange(arr, 1, arr.length)); // 맨앞 숫자를 뺀 나머지를 재귀함수를 통해 구한다.
int[] newArr = new int[arr.length]; // reverse한 것을 복사할 배열
System.arraycopy(head, 0, newArr, 0, head.length); // 재귀 함수를 통해 구한 배열을 새배열에 앞부분부터 복사
newArr[arr.length-1] = tail; // 맨처음 뺀 첫번째 숫자를 맨뒤에 추가
return newArr; // 배열 리턴
}
}
- 배열의 맨앞을 빼두고 (tail), 나머지를 재귀함수로 호출하여 저장 (head)
- 새배열을 만들어 head를 앞에 복사, 맨뒤에 tail 추가
- { 1, 2, 3, 4} -> 1 {2,3,4} -> 2 {3, 4} -> 3 {4} -> 4 {} - > 종료조건
- 리턴이 역순으로된다. {} 4 -> {4} 3 -> {4, 3} 2 -> {4, 3, 2} 1 -> {4, 3, 2, 1}
*컨텍스트 스위칭이란?
- 멀티프로세스 환경에서 실행중이던 프로세스를 중단하고 다른프로세스를 실행하는것
- 실행중이던 프로세스의 정보값들을 저장해야함
- 컨텍스트 스위칭이 자주 발생하면 오버헤드가 발생할수있다.
'CS > 알고리즘' 카테고리의 다른 글
[알고리즘] 탐욕(Greedy) 알고리즘 (0) | 2023.03.22 |
---|---|
[알고리즘] 시간복잡도 개념 (0) | 2023.03.22 |
JAVA 배열에서 새로운 요소를 추가하기 (0) | 2023.03.03 |
피보나치 수열 - 배열 (0) | 2023.02.23 |
소수(prime number) 구하기, 제곱근 사용 (0) | 2023.02.21 |
Comments