《数据结构》严蔚敏 用栈实现递归来解决hanoi问题

感觉书上对递归操作的栈理解的挺好的,有需要的可以去找一下书看一下

//hanoi problem

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

int times = 1;

void
move(char from,int n,char to)
{
	printf("%d times: Move disk %d from %c -> %c \n",times++,n,from,to);
}

int
hanoi(int n,char x,char y,char z)
{
	
	if(n == 1)
	{
		move(x,1,z);
	}
	else
	{
		hanoi(n-1,x,z,y);
		move(x,n,z);
		hanoi(n-1,y,x,z);
	}
	return times;
}

int main(int argc, char const *argv[])
{
	int times ;
	int n ;
	char x = 'X',y = 'Y',z = 'Z';

	printf("please enter the hanoi blocks: ");
	while(scanf("%d",&n) == 1)
	{
		times = hanoi(n,x,y,z);
		printf("all move %d times\n",times-1);
	}
	

	return 0;
}

非递归算法,即自己构建这么一个进栈入栈的过程,不过
用Visual Studio调试的结果,在移动同样多的盘子情况下,两种方法消耗的内存相差不大,但时间有较大差别,使用迭代的方法花费的时间是递归方法的近十倍。原因有以下几点:

迭代过程中要反复地动态创建变量,这也是时间开销差距的主要原因
递归过程由于编译过程对递归变量和递归函数有很好的优化处理,因而效率较高

迭代代码

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

typedef struct record //用于记录递归环境,放入栈中
{
	int n;
	char moveFrom;
	char moveTo;
	char swap;
	struct record *next;
} record;
typedef struct stack //定义一个栈
{
	record * records;
	int num;

} stack;
void push(record *record, stack *stack) //向栈内放置元素
{
	stack->num++;
	record->next = stack->records;
	stack->records = record;
}
record * pop(stack *stack) //从栈顶弹出元素
{
	record *record;
	stack->num--;
	record = stack->records;
	stack->records = stack->records->next;
	return record;
}

//move方法,实现将n个盘子从moveFrom柱借助swap柱移动到moveTo柱
void move(int n, char moveFrom, char moveTo, char swap)
{
	stack stack = { NULL, 0 };
	record *record1, *p_record;
	//初始化栈
	record1 = (record *)malloc(sizeof(record));
	record1->n = n, record1->moveFrom = moveFrom, record1->moveTo = moveTo;
	record1->swap = swap;
	push(record1, &stack);
	//迭代开始
	while (stack.num != 0)
	{
		//从栈中取出元素,并进行相应操作
		p_record = pop(&stack);
		if (p_record->n == 1)
		{
			printf("%c->%c\t", p_record->moveFrom, p_record->moveTo);
			free(p_record);
			continue;
		}
//记录递归环境,并放入栈中
		record *record2 = (record *)malloc(sizeof(record));
		record *record3 = (record *)malloc(sizeof(record));
		record *record4 = (record *)malloc(sizeof(record));
		record2->n = p_record->n - 1, record2->moveFrom = p_record->moveFrom,
			record2->moveTo = p_record->swap, record2->swap = p_record->moveTo;
		record3->n = 1, record3->moveFrom = p_record->moveFrom,
			record3->moveTo = p_record->moveTo, record3->swap = p_record->swap;
		record4->n = p_record->n - 1, record4->moveFrom = p_record->swap,
			record4->moveTo = p_record->moveTo, record4->swap = p_record->moveFrom;
		push(record4, &stack);
		push(record3, &stack);
		push(record2, &stack);

		//不要忘记释放内存
		free(p_record);
	}
}
int main()
{
	int n = 3;
	//调用move方法
	move(n, 'A', 'B', 'C');
	
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

五月的天气

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

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

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

打赏作者

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

抵扣说明:

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

余额充值