void hanoi(int n, int from, int temp, int to)
{
enum {ROUTINE, RA_A1, RA_A2};
int *stk;
int top =0;
int t;
int ra;
stk = (int*)malloc(sizeof(int)*n);
ra = ROUTINE;
routine:
if (n==1) printf("move %c -> %c\n", from +'A', to +'A');
else {
stk[top++]= ra;
--n;
t = to;
to = temp;
temp = t;
ra = RA_A1;
goto routine;
ra_sw:
switch(ra) {
case RA_A1:
t = to;
to = temp;
printf("move %c -> %c\n", from +'A', to +'A');
temp = from;
from = t;
ra = RA_A2;
goto routine;
case RA_A2:
ra= stk[--top];
t = temp;
temp = from;
from = t;
++n;
}
}
if (top!=0) {
goto ra_sw;
}
free(stk);
}
递归同样可以解决问题,为什么还要用非递归呢?我们必须承认,汉诺塔的运行过程可能会很长。在这个过程中,难免会有外部原因,迫使运行暂时停下来。这就需要有能够“保存进度”的能力。现在变成这样:
struct hanoisave_st {
int level;
int from;
int to;
int temp;
int ra;
int top;
};
struct hanoisave_st hanoi_save;
volatile int powerfail;
void hanoi(int level, int from, int temp, int to)
{
enum {ROUTINE, RA_A1, RA_A2};
int n;
int *stk;
int top =0;
int t;
int ra;
FILE *fp;
n= level;
stk = (int*)malloc(sizeof(int)*n);
ra = ROUTINE;
routine:
if (n==1) printf("move %c -> %c\n", from +'A', to +'A');
else {
if (powerfail) {
hanoi_save.from = from;
hanoi_save.to = to;
hanoi_save.temp= temp;
hanoi_save.level = level;
hanoi_save.ra = ra;
hanoi_save.top = top;
fp = fopen("hanoi.dat", "wb");
fwrite(&hanoi_save, sizeof(hanoi_save), 1, fp);
fwrite(stk, sizeof(int), top, fp);
fclose(fp);
free(stk);
return ;
}
stk[top++]= ra;
--n;
t = to;
to = temp;
temp = t;
ra = RA_A1;
goto routine;
ra_sw:
switch(ra) {
case RA_A1:
t = to;
to = temp;
printf("move %c -> %c\n", from +'A', to +'A');
temp = from;
from = t;
ra = RA_A2;
goto routine;
case RA_A2:
ra= stk[--top];
t = temp;
temp = from;
from = t;
++n;
}
}
if (top!=0) {
goto ra_sw;
}
free(stk);
}