Processing math: 100%
본문 바로가기

[자료구조론] 2주차: 순환

순환(Recursion)

정의 자체가 순환적인 경우 적합하다.

주어진 문제를 더 작은 동일한 문제로 분할해 해결(분할 정복: Divide and Conquer)

 

Ex) Factorial

n!n1에 대해서는 n(n1)!, n=0에 대해서는 1로 정의할 수 있다.

1
2
3
4
int factorial(int n)
{
    return (n <= 1) ? 1 : (n * factorial(n - 1));
}
cs

n!

=n×(n1)!

=n×(n1)×(n2)!

=n×(n1)×(n2)!××2!

=n×(n1)×(n2)!××2×1!

=n×(n1)×(n2)!××2×1

 

Divide and conquer

n×(n1)!에서 n은 이미 해결된 부분, (n1)!은 남아 있는 부분(더 작은 동일한 문제)

 

* 순환 알고리즘에는 반드시 순환을 멈추는 부분이 필요하다. 안 그러면 무한 호출돼서 메모리 터짐

* 대부분의 순환은 반복(iteration)으로 바꾸어 작성할 수 있다.

 

 

팩토리얼을 반복으로 구현하면 다음과 같다.

1
2
3
4
5
6
7
8
int factorial_iter(int n)
{
    int result = 1, i;
 
    for (i = 1; i <= n; result *= i++);
 
    return result;
}
cs

 

Recursion VS Iteration

시간 복잡도: 둘 다 O(n)

공간 복잡도: 순환은 함수 호출 오버헤드, 반복은 오버헤드가 적다.

-> 왜 순환인가?: 간결한 코드, 반복으로 표현하기 어려운 순환도 있음

 

 

Ex2) Power by recursion

{(x2)n2nisevenx(x2)n12nisodd

 

- 210

210=(22)102=(22)5

45=4×44=4×((42)42)=4×162

162=(162)1

2561=2561×(2562)0=256×655360

655360=1

 

반복의 경우 xn을 구하려면 대략 n번의 계산 필요 -> O(n)

순환의 경우 대략 xn에 대해 n=2k라 하면 k번의 계산 필요

log2n번의 연산을 요하므로  O(logn)

1
2
3
4
5
6
7
8
9
10
int power(int x, int n)
{
    if (n == 0)
        return 1;
    else
    {
        return (n % 2 == 0) ? power(x * x, n / 2)
                            : x * power(x * x, (n - 1/ 2);
    }
}
cs

cf. xx 대신 power(x,2)를 쓰면 power(2,2)가 무한히 호출됨

 

 

 

 

 

 

 

'강의노트 > 자료구조론' 카테고리의 다른 글