[재귀 알고리즘] 하노이 타워(The Tower of Hanoi) - 재귀, 스택
하노이 타워 문제
하노이 타워 문제는 재귀적으로 해결할 수 있는 대표적인 문제이다.
조건 : 원반은 한번에 한 개씩 옮길 수 있고 큰 원반이 작은 원반 위에 올라가서는 안된다.
원반을 A에서 C로 모두 옮기면 된다.
하노이 타워 패턴
- A에 있는 n개의 원반 중 맨 아래에 있는 n번째 원반을 제외한 나머지 원반을 모두 B로 옮긴다.
- A에 남은 하나의 원반을 C로 옮긴다.
- B의 모든 원반을 C로 옮긴다.
결론을 먼저 말해서 헷갈릴 수도 있지만 하노이 타워를 원반 2개부터 하나씩 증가시키면서 해보면 같은 패턴이 반복 되는 걸 알 수 있다.
하노이 타워의 최소 단위는 2개의 원반이 있을 때인데 작은 원반을 A->B로 옮기고, 큰 원반을 A->C로 옮기고, 작은 원반을 B->C로 옮기면 된다.
원반의 갯수가 늘어났을때도 가장 큰 원반과 나머지 원반으로 두 개로 생각하면 2개의 원반이 있을 때의 반복이 된다.(나머지 원반을 하나의 원반으로 치환한다고 생각하면 좋을 듯 하다.)
Code
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #include <stdio.h> int Stack[10]; int cur; //***** Stack 이용을 위한 함수 *****// void InitStack() { cur = -1; } void Push(int data) { if (cur >= 10 - 1) { printf("Stack overflow!!!\n"); return; } Stack[++cur] = data; } int Pop() { if (cur < 0) { printf("Stack is already empty!!!\n"); return 0; } return Stack[cur--]; } int IsEmpty() { if (cur < 0) return 1; else return 0; } /////////////////////////////////////// void Print(int n, int from, int to) { printf("원반%d를 %c에서 %c로 이동\n", n, from, to); } // 하노이 타워 반복문 구현 함수(스택 이용) void Hanoi(int n, int from, int by, int to) { int bContinue = 1; InitStack(); while (bContinue) { while (n > 1) { Push(to); Push(by); Push(from); Push(n); --n; Push(to); to = by; by = Pop(); } Print(n, from, to); if (!IsEmpty()) { n = Pop(); from = Pop(); by = Pop(); to = Pop(); Print(n, from, to); --n; Push(from); from = by; by = Pop(); } else bContinue = 0; } } // 하노이 타워 재귀 구현 함수 void HanoiTowerMove(int num, char from, char by, char to){ if (num == 1){ printf("원반1을 %c에서 %c로 이동\n", from, to); } else{ HanoiTowerMove(num - 1, from, to, by); printf("원반%d를 %c에서 %c로 이동\n", num, from, to); HanoiTowerMove(num - 1, by, from, to); } } int main(int arc, char** argv){ printf("하노이 타워 재귀 구현\n"); HanoiTowerMove(3, 'A', 'B', 'C'); printf("\n"); printf("하노이 타워 반복문 구현\n"); Hanoi(3, 'A', 'B', 'C'); return 0; } | cs |
정리
코드의 가독성은 재귀를 이용한 함수가 좋지만 성능면에 있어서는 스택을 이용한 함수가 좋다.
스택 사이즈와 원반 갯수를 늘려서 테스트 해보자.
'아카이브 > 알고리즘' 카테고리의 다른 글
Maximum Contiguous Subsequence Sum(MCSS) 알고리즘 분석 (0) | 2015.10.05 |
---|---|
[알고리즘 사이트] 알고리즘 문제 풀이 사이트 (2) | 2015.07.13 |
[재귀 알고리즘] 피보나치 수열(재귀, 꼬리 재귀, 반복문) (0) | 2015.07.08 |
[재귀] 재귀 vs 꼬리 재귀 (0) | 2015.07.08 |
[탐색 알고리즘] 순차 탐색 알고리즘 vs 이진 탐색 알고리즘 (0) | 2015.07.07 |