问题描述:
问题分析:
元素只能在一端进行操作,因而选择栈数据结构。复杂问题可以分而治之,不断递归可解决问题。
递归基:当X上只有一个圆盘时,可直接移动到Z;
递归分解:当X上有n个圆盘时,可先将n-1个圆盘移动到Y,Z作为辅助盘;再将X上n盘移动到Z;最后将Y上n-1个盘移动到Z,X作为辅助盘。
代码实现
#include <stdio.h>
#include <stdlib.h>
//宏定义
#define OVERFLOW -1
#define STACKEMPTY -2
typedef int ElemType;
//栈节点
typedef struct LNode
{
ElemType data;
LNode *next;
}LNode, *LinkList;
typedef struct stack
{
LinkList top;
}STACK;
/* 栈相关接口
*
*/
void InitStack(STACK &S);
void Push(STACK &S, ElemType e);
void Pop(STACK &S, ElemType *e);
ElemType GetTop(STACK S, ElemType *e);
int StackEmpty(STACK S);
//初始化栈
void InitStack(STACK &S)
{
S.top = NULL;
}
//入栈
void Push(STACK &S, ElemType e)
{
LinkList p;
p = (LinkList)malloc(sizeof(LNode));
if (!p) exit(OVERFLOW);
p->data = e;
p->next = S.top;
S.top = p;
}
//出栈
void Pop(STACK &S, ElemType *e)
{
LinkList p;
if (StackEmpty(S)) exit(STACKEMPTY);
*e = S.top->data;
p = S.top;
S.top = p->next;
free(p);
}
//获取栈顶元素
ElemType GetTop(STACK S, ElemType *e)
{
if (StackEmpty(S)) exit(STACKEMPTY);
*e = S.top->data;
}
//输出栈
void printStack(STACK S)
{
LinkList p;
p = S.top;
printf("栈: ");
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//判空
int StackEmpty(STACK S)
{
return S.top == NULL;
}
/* 解题思路
* 如果有一个盘子,直接从X移到Z即可。
* 如果有n个盘子要从X移到Z,Y作为辅助。问题可以转化为,先将上面n-1个从X移动到Y,Z作为辅助,然 后将第n个从X移动到Z,最后将剩余的n-1个从Y移动到Z,X作为辅助。
*/
//将A栈顶元素移动到B栈顶
void move(STACK &Sa, STACK &Sb)
{
ElemType e;
Pop(Sa, &e);
Push(Sb, e);
}
//将塔座X上n个圆盘移到塔座Z,Y做辅助塔
void hanoi(int n, STACK &X, STACK &Y, STACK &Z)
{
if (n == 1)
{
move(X, Z); //将塔座X上圆盘直接移到塔座Z
return;
}
hanoi(n - 1, X, Z, Y); //将塔座X上n-1个圆盘移到塔座Y,Z做辅助塔
move(X, Z); //将塔座X上圆盘直接移到塔座Z
hanoi(n - 1, Y, X, Z); //将塔座Y上n-1个圆盘移到塔座Z,X做辅助塔
}
//测试
int main(void)
{
STACK Sx, Sy, Sz;
InitStack(Sx);
InitStack(Sy);
InitStack(Sz);
int i, n = 20;
for (i = 20; i >= 1; i--)
{
Push(Sx, i);
}
printStack(Sx);
hanoi(n, Sx, Sy, Sz);
printStack(Sz);
return 0;
}