题目详情我就不描述了,很经典的问题,然后问题是,用递归来做是很好理解,很顺理成章的问题,但是用非递归,对我来说感觉很别扭,断断续续看了两个都领悟,网上对于非递归的方法其实也说的不清不楚,也可能是我比较笨,我尝试讲一下我的理解。
首先理解什么是汉诺塔,可以看这个视频:「递归练习」汉诺塔
看完之后,然后可以列一下汉诺塔的解法:
盘数 | 解法 |
1 | a->c |
2 | a->b a->c b->c |
3 | a->c a->b c->b a->c b->a b->c a->c |
4 | 略 |
1、将0到n-1盘从a移到b;
2、将第n盘从a移到c;
3、最后把0到n-1盘从b移到c;
在程序中就是,慢慢将n-1分解,直到1。
那么用非递归方法利用就是堆栈先进后出的特性,解决问题时,堆栈内情况如下:
取盘数为3,进行模拟堆栈操作
循环的思路就是,当栈不空时,将栈顶抛出,然后判断栈顶是否为1,不是就继续分解,是则输出;
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define STACKSIZE 100
typedef struct
{
int n;
char a;
char b;
char c;
}ElementType;
typedef int Position;
typedef struct snode* PtrToSnode;
struct snode
{
ElementType *data;
Position top;
int maxsize;
};
typedef PtrToSnode mystack;
ElementType ERROR;
mystack create(int maxsize);
bool isEmpty(mystack ms);
bool pushdata(mystack ms, ElementType x);
ElementType popdata(mystack ms);
void hanoi(int pan);
void hanoi(int pan)
{
ElementType tmp, toPush;
mystack stk = create(STACKSIZE);
tmp.a = 'a'; tmp.b = 'b'; tmp.c = 'c'; tmp.n = pan;
pushdata(stk, tmp);
while(!isEmpty(stk))
{
tmp = popdata(stk);
if(tmp.n == 1)
{
printf("%c -> %c\n", tmp.a, tmp.c);
}
else
{
toPush.n = tmp.n-1; toPush.a = tmp.b; toPush.b = tmp.a, toPush.c = tmp.c;
pushdata(stk, toPush);
toPush.n = 1; toPush.a = tmp.a; toPush.b = tmp.b, toPush.c = tmp.c;
pushdata(stk, toPush);
toPush.n = tmp.n-1; toPush.a = tmp.a; toPush.b = tmp.c, toPush.c = tmp.b;
pushdata(stk, toPush);
}
}
}
mystack create(int maxsize)
{
mystack ms = (mystack)malloc(sizeof(struct snode));
ms->data = (ElementType *)malloc(maxsize*sizeof(ElementType));
ms->maxsize = maxsize;
ms->top = -1;
return ms;
}
bool isEmpty(mystack ms)
{
return (ms->top == -1);
}
bool isFull(mystack ms)
{
return (ms->top == ms->maxsize - 1);
}
bool pushdata(mystack ms, ElementType x)
{
if(isFull(ms))
{
printf("Stack is full.\n");
return false;
}
else
{
ms->data[++(ms->top)] = x;
return true;
}
}
ElementType popdata(mystack ms)
{
if(isEmpty(ms))
{
printf("Stack is empty.\n");
return ERROR;
}
else
{
return (ms->data[(ms->top)--]);
}
}
int main()
{
int n;
scanf("%d", &n);
hanoi(n);
system("pause");
}