汉诺塔的非递归实现(堆栈)

汉诺塔问题本身用递归实现是很简便的,本题其实还是为了加深对堆栈的理解运用,所以用标准的堆栈来模拟递归的过程。

题目

借助堆栈以非递归(循环)方式求解汉诺塔的问题(n, a, b, c),即将N个盘子从起始柱(标记为“a”)通过借助柱(标记为“b”)移动到目标柱(标记为“c”),并保证每个移动符合汉诺塔问题的要求。

输入格式:

输入为一个正整数N,即起始柱上的盘数。

输出格式:

每个操作(移动)占一行,按柱1 -> 柱2的格式输出。

输入样例:

3

输出样例:

a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c

思路:

不用递归用循环,就需要用到堆栈先进后出的特性来模拟递归,将问题放入堆栈,然后不断将栈顶问题分解,将分解的n-1个问题放入堆栈,这样循环直到堆栈为空。以3个为例。
在这里插入图片描述
根据汉诺塔问题的思路,构造堆栈,模拟这个过程,还是以3个为例,可以对照代码看(画的有点丑)
在这里插入图片描述
在这里插入图片描述

代码

定义堆栈及函数声明

#include<stdio.h>
#include<stdlib.h>

#define Maxsize 100
typedef enum { False, True }Bool;
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 Stack;

Stack CreateStack(int MaxSize);
bool IsEmpty(Stack S);
void Push(Stack S, ElementType X);
ElementType Pop(Stack S);

Hanoi函数及主函数

void Hanoi(int n) {
	Stack S;
	ElementType P, toPush;
	S = CreateStack(Maxsize);
	P.N = n; P.A = 'a'; P.B = 'b'; P.C = 'c';
	Push(S, P);//将初始问题放入堆栈(n,a,b,c)
	while (1) {
		P = Pop(S);
		if (P.N == 1) {
			if (IsEmpty(S)) {
				printf("%c -> %c", P.A, P.C);
				break;
			}
			else {
				printf("%c -> %c\n", P.A, P.C);
			}
		}
		else {
			toPush.N = P.N - 1;
			toPush.A = P.B;
			toPush.B = P.A;
			toPush.C = P.C;
			Push(S, toPush);//将第二个待解子问题入栈(n-1,b,a,c)
			toPush.N = 1;
			toPush.A = P.A;
			toPush.B = P.B;
			toPush.C = P.C;
			Push(S, toPush);//将可直接求解的子问题(1,a,b,c)入栈
			toPush.N = P.N - 1;
			toPush.A = P.A;
			toPush.B = P.C;
			toPush.C = P.B;
			Push(S, toPush);//将第一个待解子问题(n-1,a,c,b)入栈
		}
	}
}
int main() {
	int N;
	scanf("%d",&N);
	Hanoi(N);
	return 0;
}

其他函数


Stack CreateStack(int MaxSize) {
	Stack S = (Stack)malloc(sizeof(struct SNode));
	S->Data = (ElementType*)malloc(Maxsize * sizeof(ElementType));
	S->Top = -1;
	S->MaxSize = MaxSize;
	return S;
}

bool IsEmpty(Stack S) {
	return (S->Top == -1);
}

void Push(Stack S, ElementType X) {
	S->Data[++(S->Top)] = X;
}
ElementType Pop(Stack S) {
	return S->Data[(S->Top)--];
}

  • 21
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.别拖至春天.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值