ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 재귀
    자료구조와 알고리즘/자료구조 2023. 3. 2. 10:05

    1. 함수의 재귀적 호출

    함수의 재귀적 호출이란, 함수 내에서 자기 자신을 다시 호출하는 것

    간단하게 이해하는 방향은 하나의 함수는 원본이 있고,

    재귀호출이 발생하면, 복사본이 만들어져서 호출한다고 생각해보자.

     

     

    간단한 예제를 통한 재귀 호출의 흐름  

    Num 3으로 시작해서 조건 검사

    -> true면 호출종료, falsenum=2recursive 재호출

    -> 종료조건 만족 시,

    recursive (0) 반환 -> recursive(1)반환 -> recursive(3)반환

    순서로 이어진다. 

     

    *재귀함수는 탈출조건이 필요하다.

    * recursive호출을 기준으로 위 문장은 최종 반환 전 모든 함수가 반복하는 것,

    recursive 후는 탈출조건 만족 후 함수가 반환을 시작하면서 반복할 문장 

     

     

     

    예제2 팩토리얼 계산

    간단한 팩토리얼 계산이다.

    num =5 라면 

    fRecursive(5)의 값은  

    num * fRecursive(num-1) 

    이를 대입해보면,

    5 *  fRecursive(4)

    fRecusive(4)값은 

    4*fRecursive(3)으로 종료조건까지 이어지는 것

     

     

     

    종료조건 fRecursive(0)에서 return을 시작하면,

    리턴전에 fRecursive(0)을 호출한 fRecursive(1)->2->3 ..순으로 값을 리턴하기 시작하면서, 

    마지막 fRecursive(5)가 리턴하며 함수 호출을 마무리한다. 

     

    예제3 피보나치 수열 

    0 1 1 2 3 5의 피보나치 수열을 표현 한 것이다.

     

     

     

     

     

     

     

     

     

     

    예제4 이진탐색 알고리즘의 재귀적 구현

    이진탐색 알고리즘은 다음 두가지를 반복한다.

    -탐색 범위의 중앙에 목표값이 저장되었는지 확인

    -저장되지 않았다면 탐색 범위를 반으로 줄여서 다시 탐색 시작

     

    이진탐색 알고리즘의 종료조건은 다음과 같다.

    -탐색을 종료하는 지점은 시작 위치를 의미하는 first가 끝을 의미하는

    last보다 커지는 경우이다.

     

    *재귀함수는 계산해야할 값이 커질 수록 함수의 재귀적 호출이 많아지고, 때에 따라 성능이 매우 떨어진다.

     

     

    2. 하노이 타워문제 

    재귀함수의 대표적인 예제인 하노이 타워 문제를 풀어보자.

     

     

     

     

     

     

    그림출처https://shoark7.github.io/programming/algorithm/tower-of-hanoi

    A에 있는 타워를 C로 옮기는 문제이다. 제약 조건은 다음과 같다.

    -한 번에 하나씩만 옮길 수 있다.

    -옮기는 과정에서 작은 원반 위에 큰 원반이 올려져서는 안된다.

     

    원반이 2개라고 가정해보자.

    그렇다면 맨위에 원반을 B로 옮기고 다음 원반을 C로 옮긴 후 B의 원반을 C로 옮기면 될 것이다. 

    원반이 3개라면 어떨까?

    A에 맨 아래 원반만 남을 때까지 가장 큰 원반을 제외한 나머지 원반(1,2)을 B로 옮기고, 가장 큰 원반(3)을 C로 옮긴 뒤 다시 B에 있는 원반(1,2)을 C로 옮기면 될 것이다.  원반이 4,5..n개 인 상태에서도 크게 보면 위와 같은 과정의 반복이다.

     

    -하노이 타워 문제 반복패턴

    맨 마지막의 1개 원반을 제외하고 나머지를 b에 옮기고, 마지막 원반을 c에 옮긴 후 다시 b->c로 나머지 원반을 옮기면 된다.

    즉,

    1.작은 원반들 n-1개를  a에서 b로 이동

    2.큰 원반 1개를 a ->c 로 이동

    3.다시 작은 원반들 n-1개를 b->c로 이동시키는 과정이다. 

     

    위와 같은 반복 패턴을 재귀로 표현해보자. HanoiTowerMove(int 원반의 갯수(n), char 시작from(A), char 중간by(B),char 최종to(C))

    1. 먼저 종료 조건을 생각해보자 움직일 원반이 한 개라면, A>C로 한 개의 원반만 옮기면 그만이다.

    If(num==1) { 원반 1A->C }

    2. 다음으로 원반 n개를 C로 옮기는 과정 중 첫 번째로 해야 할 일인 n-1개의 원반을 A->B로 옮기는 과정이 필요하다.

    HanoiTowerMove(n-1,from,to,by)  A -> Bn-1개의 원반을 이동 

    3. 다음 단계는 큰 원반을 A->C로 옮기는 단계이다.

    System.out.printf(“원반 %d%c%c로 이동 \n”,num,from,to); (HanoiTowerMove의 첫 호출의 매개변수 from A, to는 C)

    4. 마지막 단계는 n-1개의 작은 원반을 다시 B->C로 옮기는 과정이다.

    HanoiTowerMove(n-1,by,from,to) 이를 종합하면 다음과 같이 재귀적 호출 함수를 만들 수 있다.

    -------------------------------------------------------------------------------------------------------------------------------------------------

    자료구조를 공부하기 전에 재귀호출에 대해 간단하게 복습 겸 몇가지 예제를 풀어보았다. 

    열심히 더 해야지! 

     

    참고도서: 열혈자료구조

Designed by Tistory.