CH 02 재귀

honeyricecake·2022년 1월 25일
0

자료구조

목록 보기
5/36

이 게시글은 윤성우 선생님의 자료구조 강의를 수강 후 나름대로의 내용 정리를 한 것임을 미리 밝힙니다.
스스로의 복습을 위해 작성한 글이므로 심층있는 학습을 위해서는 책의 구매 및 강의수강을 권장합니다.

02 - 1 함수의 재귀적 호출의 이해

EX.1 피보나치 수열

피보나치 수열의 5번째 항을 예시로 구해보자.

EX.2 별찍기 - 10

(참고) https://velog.io/@honeyricecake/%EB%B3%84%EC%B0%8D%EA%B8%B0-10

N = 27일 때를 예시로 보자.

이렇게 이해하고나면 재귀에 대한 이해도가 한층 높아지고 이후 재귀함수의 호출에 대해 모든 순서를 고민해보지 않아도 스스로의 논리에 대한 의심없이 구현할 수 있게 될 것이다.

02 - 2 재귀의 활용

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

<재귀로 구현할 수 있다는 확신을 가질 수 있는 이유>

mid = (first + last) / 2 로 구하고
arr[mid]가 target과 같은지 검사하는 일련의 과정을 반복하기 때문

내 코드

int binsearch(int* arr,int first, int last, int target)
{
	if (first >= last) return -1;
	int mid = (first + last) / 2;
	if (arr[mid] == target) return mid;
	else if (arr[mid] > target) return binsearch(arr, first, mid - 1, target);
	else return binsearch(arr, mid + 1, last, target);
}

하노이 타워

https://www.acmicpc.net/problem/11729

아이디어

1개 더 원반을 추가하면
원래 1번에 있던 원반을 3번으로 옮기는 과정을 2번으로 옮기는 과정으로 바꾸면 되므로

함수를
Hanoi(n, from, by, to)라 하면
처음에는 Hanoi(n -1 , from, to , by)를 출력하면 된다.
그리고 1 3 을 출력한 후

원래 1번에 있던 원반을 3번으로 옮기는 과정이 2번에 있는 원반을 3번으로 옮기는 과정이 되므로
Hanoi(n - 1,by, from, to)를 출력하면 된다.

내 코드

#include <stdio.h>

void Hanoi(int n, char from, char by, char to)
{
	if (n == 1) printf("%d %d\n", from, to); // n이 1이면 당연히 from에서 to로 이동, 그리고 from과 to가 바뀌면 즉, Hanoi(1, from, to ,by)가 들어오면 당연히 n == 1에서도 from에서 원래 by였던 곳으로 간다.
    
    이는 Hanoi(N,1,2,3)에서 Hanoi(N,1,3,2)를 받으면 by가 3이 되고 to가 2가 된다고 해석해도 된다.
	else
	{
		Hanoi(n - 1, from, to, by);
		printf("%d %d\n",from,to);
		Hanoi(n - 1, by, from, to);
	}
}

int main()
{
	int x, N;
	int y = 1;
	scanf("%d", &N);
	x = N;
	while (x--)
	{
		y *= 2;
	}
	printf("%d\n", y - 1);
	Hanoi(N, 1, 2, 3);
	return 0;
}

또는

#include <stdio.h>

void Hanoi(int n, char from, char by, char to)
{
	if(n == 1) printf("%d %d", from, to);
	else if (n == 2)
	{
		printf("%d %d\n", from, by);
		printf("%d %d\n", from, to);
		printf("%d %d\n", by, to);
	}
	else
	{
		Hanoi(n - 1, from, to, by);// Hanoi(n - 1, 1,3,2)
        즉, 여기서는 출발지가 1 경유지가 3 목적지가 2
		printf("%d %d\n",from,to);
		Hanoi(n - 1, by, from, to);
        // 여기서는 출발지가 2 경유지가 1 목적지가 3
	}
}

int main()
{
	int x, N;
	int y = 1;
	scanf("%d", &N);
	x = N;
	while (x--)
	{
		y *= 2;
	}
	printf("%d\n", y - 1);
	Hanoi(N, 1, 2, 3);
	return 0;
}

두번째 코드가 처음에 메모리가 초과됐었다.
n = 1을 불러오는 과정에서 시간이 많이 걸릴 것 같아서 n == 2를 바로 썼는데
n == 1일때를 따로 적어주지 않아서 else 문에 들어가서
n이 무한히 줄어들었기 때문이다.

재귀함수의 시간을 줄이고자 할 때 각별히 주의해야할 점인 것 같다.

또 다른 교훈도 얻었다.
백준에서 에러가 나면 다 이유가 있다
이게 안 될리가 없다고 하지 말고 조금 수정해보고 막 제출하지 말자...

흑흑......

0개의 댓글