CCI_Q3.4
本文参考该作者文章当作编程笔记: 作者:Hawstein 出处:http://hawstein.com/posts/ctci-solutions-contents.html
Q:
编程解决汉诺塔问题,使用数据结构栈.
思路:
1.递归:分成3个状态:
- 将src上的1~n-1个盘子借助dst移到bri上。
- 将src上的剩下的第n个盘子移动到dst上。
- 将bri上的1~n-1个盘子借助src移动到dst上。
参考:http://hawstein.com/posts/3.4.html
2.使用栈的非递归:
另一种汉诺塔移动方式:
- 3个柱子呈品字型放置,形成循环。如果盘子数目n是奇数,那么排放方式:A-》C-》B;如果是偶数,那么排列方式:A-》B-》C。
- 汉诺塔总共移动的步数是2n-1步。
- 将1号盘子由当前柱子(1号)移动到下一个柱子(2号)。
- 在1号柱子和3号柱子中选择一个非空的或者盘子比较小的柱子,将其上面的盘子移动到另外一个。
- 重复3和4,直到到达总步数。
- 成功。
参考:http://blog.minidx.com/2008/01/30/457.html
3.非递归
参考:http://www.zdyi.com/blog/hanoi/817
CODE:
1和2:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<math.h> 4 #define less(A,B)(A<B) 5 #define N 5 6 #define Null 0 7 void hanoi(int n,char src,char bri,char dst) 8 { 9 if(n==0) 10 return; 11 hanoi(n-1,src,dst,bri); 12 printf("move %d from %c to %c\n",n,src,dst); 13 hanoi(n-1,bri,src,dst); 14 } 15 typedef struct stack_h 16 { 17 int s[N]; 18 int cur; 19 char name; 20 //void (*stack_hPush)(int,struct stack_h*); 21 //int (*stack_hPop)(int); 22 //int (*stack_hTop)(int); 23 }Stack_h; 24 void stack_hPush(int item,Stack_h *h) 25 { 26 if(h->cur == (N-1)) 27 return; 28 h->s[++h->cur]=item; 29 } 30 int stack_hPop(Stack_h *h) 31 { 32 if(h->cur==Null) 33 return Null; 34 return h->s[h->cur--]; 35 } 36 int stack_hTop(Stack_h *h) 37 { 38 if(h->cur!=Null) 39 return h->s[h->cur]; 40 return Null; 41 } 42 int main() 43 { 44 hanoi(4,'A','B','C'); 45 printf("*****************************\n"); 46 Stack_h h1={{Null,4,3,2,1},N-1,'A'}, 47 h2={{Null},Null,'B'}, 48 h3={{Null},Null,'C'}; 49 if((N-1)%2!=0) 50 { 51 h2.name='C'; 52 h3.name='B'; 53 } 54 int step_num=pow(2,N-1)-1 , step_cout=0; 55 while(step_cout<=step_num) 56 { 57 if(stack_hTop(&h1)==1) 58 { 59 stack_hPush(stack_hPop(&h1),&h2); 60 printf("move 1 from %c to %c\n",h1.name,h2.name); 61 ++step_cout; 62 if(step_cout==step_num) 63 break; 64 if(stack_hTop(&h1)==Null) 65 { 66 stack_hPush(stack_hPop(&h3),&h1); 67 printf("move %d from %c to %c\n", 68 stack_hTop(&h1),h3.name,h1.name); 69 } 70 else if(stack_hTop(&h3)==Null) 71 { 72 stack_hPush(stack_hPop(&h1),&h3); 73 printf("move %d from %c to %c\n", 74 stack_hTop(&h3),h1.name,h3.name); 75 } 76 else 77 { 78 if(less(stack_hTop(&h1) , stack_hTop(&h3))) 79 { 80 stack_hPush(stack_hPop(&h1),&h3); 81 printf("move %d from %c to %c\n", 82 stack_hTop(&h3),h1.name,h3.name); 83 } 84 else 85 { 86 stack_hPush(stack_hPop(&h3),&h1); 87 printf("move %d from %c to %c\n", 88 stack_hTop(&h1),h3.name,h1.name); 89 } 90 } 91 } 92 else if(stack_hTop(&h2)==1) 93 { 94 stack_hPush(stack_hPop(&h2),&h3); 95 printf("move 1 from %c to %c\n",h2.name,h3.name); 96 ++step_cout; 97 if(step_cout==step_num) 98 break; 99 if(stack_hTop(&h1)==Null) 100 { 101 stack_hPush(stack_hPop(&h2),&h1); 102 printf("move %d from %c to %c\n", 103 stack_hTop(&h1),h2.name,h1.name); 104 } 105 else if(stack_hTop(&h2)==Null) 106 { 107 stack_hPush(stack_hPop(&h1),&h2); 108 printf("move %d from %c to %c\n", 109 stack_hTop(&h2),h1.name,h2.name); 110 } 111 else 112 { 113 if(less(stack_hTop(&h1) , stack_hTop(&h2))) 114 { 115 stack_hPush(stack_hPop(&h1),&h2); 116 printf("move %d from %c to %c\n", 117 stack_hTop(&h2),h1.name,h2.name); 118 } 119 else 120 { 121 stack_hPush(stack_hPop(&h2),&h1); 122 printf("move %d from %c to %c\n", 123 stack_hTop(&h1),h2.name,h1.name); 124 } 125 } 126 } 127 else 128 { 129 stack_hPush(stack_hPop(&h3),&h1); 130 printf("move 1 from %c to %c\n",h3.name,h1.name); 131 ++step_cout; 132 if(step_cout==step_num) 133 break; 134 if(stack_hTop(&h3)==Null) 135 { 136 stack_hPush(stack_hPop(&h2),&h3); 137 printf("move %d from %c to %c\n", 138 stack_hTop(&h3),h2.name,h3.name); 139 } 140 else if(stack_hTop(&h2)==Null) 141 { 142 stack_hPush(stack_hPop(&h3),&h2); 143 printf("move %d from %c to %c\n", 144 stack_hTop(&h2),h3.name,h2.name); 145 } 146 else 147 { 148 if(less(stack_hTop(&h3) , stack_hTop(&h2))) 149 { 150 stack_hPush(stack_hPop(&h3),&h2); 151 printf("move %d from %c to %c\n", 152 stack_hTop(&h2),h3.name,h2.name); 153 } 154 else 155 { 156 stack_hPush(stack_hPop(&h2),&h3); 157 printf("move %d from %c to %c\n", 158 stack_hTop(&h3),h2.name,h3.name); 159 } 160 } 161 } 162 ++step_cout; 163 } 164 165 return 0; 166 }
缺点:
使用栈的非递归2的程序写的很烂.有很多地方可以优化:例如可以把3个栈设为数组,通过不断加下标i,然后和3取余,确定柱子。还可以把重复的写成一个函数。等等。