递归及非递归汉诺塔
程序代码:
#include <stdio.h> #include <stdlib.h> #include <math.h> void move(char, char); void hanoi1(int, char, char, char); void hanoi2(int, char, char, char); int get_dis_size(int); int * calc_dis_value(int, int *, int); void even_next(char *, char *, char, char, char, int); void odd_next(char *, char *, char, char, char, int); int main(void) { int n; scanf("%d", &n); hanoi2(n, 'A', 'B', 'C'); return 0; } void move(char from, char to) { printf("%c -> %c\n", from, to); } void hanoi1(int n, char a, char b, char c) { if(n == 1) move(a, c); else if(n > 1) { hanoi1(n - 1, a, c, b); move(a, c); hanoi1(n - 1, b, a, c); } } void hanoi2(int n, char a, char b, char c) { int size = get_dis_size(n); int * dis_arr = (int *)calloc(size, sizeof(int)); int i, j = 0; int p = (int)pow(2, n); char prev[2]; if(size || n > 0) { calc_dis_value(n, dis_arr, size); if(n % 2) move(a, c); else move(a, b); prev[0] = a; for(i = 2; i < p; i++) { if(i % 2) odd_next(prev + 0, prev + 1, a, b, c, n); else even_next(prev + 0, prev + 1, a, b, c, n); if(i == dis_arr[j]) { move(prev[1], prev[0]); j++; } else { move(prev[0], prev[1]); } } } free(dis_arr); } int get_dis_size(int n) { int dis_size = 1; int i; if(n < 3) return 0; else if(n > 3) for(i = 4; i <= n; i++) dis_size = i % 2 ? dis_size * 2 + 1 : dis_size * 2; return dis_size; } int * calc_dis_value(int n, int * dis_arr, int size) { int i, j, k, p, tmp; if(n > 2) { for(i = 0, j = 3; i < size; j++) { p = (int)pow(2, j); if(j % 2) { tmp = i; dis_arr[i++] = p / 2; for(k = tmp - 1; k >= 0; k--) dis_arr[i++] = p - dis_arr[k]; } else { for(k = i - 1; k >= 0; k--) dis_arr[i++] = p - dis_arr[k]; } } } return dis_arr; } void odd_next(char * prev1, char * prev2, char a, char b, char c, int n) { if(n % 2) { if(*prev2 == a) *prev1 = b; else if(*prev2 == b) *prev1 = c; else *prev1 = a; } else { if(*prev2 == a) *prev1 = c; else if(*prev2 == b) *prev1 = a; else *prev1 = b; } } void even_next(char * prev1, char * prev2, char a, char b, char c, int n) { if(n % 2) { if(*prev1 == a) *prev2 = b; else if(*prev1 == b) *prev2 = c; else *prev2 = a; } else { if(*prev1 == a) *prev2 = c; else if(*prev1 == b) *prev2 = a; else *prev2 = b; } } /* n = 1 n = 2 n = 3 n = 4 n = 5 n = 6 n = 7 1 A -> C A -> B A -> C A -> B A -> C A -> B A -> C 2 A -> C A -> B A -> C A -> B A -> C A -> B 3 B -> C C -> B B -> C C -> B B -> C C -> B 4 C -> A (A -> C) B -> A (A -> B) C -> A (A -> C) B -> A (A -> B) C -> A (A -> C) 5 B -> A C -> A B -> A C -> A B -> A 6 B -> C C -> B B -> C C -> B B -> C 7 A -> C A -> B A -> C A -> B A -> C 8 A -> C A -> B A -> C A -> B 9 B -> C C -> B B -> C C -> B 10 B -> A C -> A B -> A C -> A 11 C -> A B -> A C -> A B -> A 12 C -> B (B -> C) B -> C (C -> B) C -> B (B -> C) B -> C (C -> B) 13 A -> B A -> C A -> B A -> C 14 A -> C A -> B A -> C A -> B 15 B -> C C -> B B -> C C -> B 16 C -> A (A -> C) B -> A (A -> B) C -> A (A -> C) 17 B -> A C -> A B -> A 18 B -> C C -> B B -> C 19 A -> C A -> B A -> C 20 A -> B (B -> A) A -> C (C -> A) A -> B (B -> A) 21 C -> B B -> C C -> B 22 C -> A B -> A C -> A 23 B -> A C -> A B -> A 24 B -> C C -> B B -> C 25 A -> C A -> B A -> C 26 A -> B A -> C A -> B 27 C -> B B -> C C -> B 28 C -> A (A -> C) B -> A (A -> B) C -> A (A -> C) 29 B -> A C -> A B -> A 30 B -> C C -> B B -> C 31 A -> C A -> B A -> C 32 A -> C A -> B 33 B -> C C -> B 34 B -> A C -> A 35 C -> A B -> A 36 C -> B (B -> C) B -> C (C -> B) 37 A -> B A -> C 38 A -> C A -> B 39 B -> C C -> B 40 B -> A C -> A 41 C -> A B -> A 42 C -> B B -> C 43 A -> B A -> C 44 A -> C (C -> A) A -> B (B -> A) 45 B -> C C -> B 46 B -> A C -> A 47 C -> A B -> A 48 C -> B (B -> C) B -> C (C -> B) 49 A -> B A -> C 50 A -> C A -> B 51 B -> C C -> B 52 B -> A (A -> B) C -> A (A -> C) 53 C -> A B -> A 54 C -> B B -> C 55 A -> B A -> C 56 A -> C A -> B 57 B -> C C -> B 58 B -> A C -> A 59 C -> A B -> A 60 C -> B (B -> C) B -> C (C -> B) 61 A -> B A -> C 62 A -> C A -> B 63 B -> C C -> B 64 C -> A (A -> C) 65 B -> A 66 B -> C 67 A -> C 68 A -> B (B -> A) 69 C -> B 70 C -> A 71 B -> A 72 B -> C 73 A -> C 74 A -> B 75 C -> B 76 C -> A (A -> C) 77 B -> A 78 B -> C 79 A -> C 80 A -> B (B -> A) 81 C -> B 82 C -> A 83 B -> A 84 B -> C (C -> B) 85 A -> C 86 A -> B 87 C -> B 88 C -> A 89 B -> A 90 B -> C 91 A -> C 92 A -> B (B -> A) 93 C -> B 94 C -> A 95 B -> A 96 B -> C 97 A -> C 98 A -> B 99 C -> B 100 C -> A (A -> C) 101 B -> A 102 B -> C 103 A -> C 104 A -> B 105 C -> B 106 C -> A 107 B -> A 108 B -> C (C -> B) 109 A -> C 110 A -> B 111 C -> B 112 C -> A (A -> C) 113 B -> A 114 B -> C 115 A -> C 116 A -> B (B -> A) 117 C -> B 118 C -> A 119 B -> A 120 B -> C 121 A -> C 122 A -> B 123 C -> B 124 C -> A (A -> C) 125 B -> A 126 B -> C 127 A -> C 可以看出移动的过程是一个交叉顺序链,可是在有些位置会被断开: n = 1: 无 n = 2: 无 n = 3: 4 n = 4: 4 12 n = 5: 4 12 16 20 28 n = 6: 4 12 16 20 28 36 44 48 52 60 n = 7: 4 12 16 20 28 36 44 48 52 60 64 68 76 80 84 92 100 108 112 116 124 (括号中是正确的顺序),我们只需要在断开的时候把过程反过来就行了,可以看出这些断开点有规律可寻,如当n = 7时,4 + 124 = 2 ^ 7,12 + 116 = 2 ^ 7,16 + 112 = 2 ^ 7... 64 + 64 = 2 ^ 7,这是一些以2 ^ (n - 1)对称的数。但这里有一个问题,就是如果n是奇数,那么 2 ^ (n - 1)存在,而n是偶数2 ^ (n - 1)不存在,需要在一个循环里判断。 */
hanoi1是汉诺塔递归移动函数。
hanoi2是汉诺塔迭代移动函数。
[ 本帖最后由 lz1091914999 于 2011-8-23 17:18 编辑 ]