hanoi的使用递归和使用栈来解决

hanoi塔问题

hanoi塔问题就是讲该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘,三根柱子分别为起始柱x、辅助柱y及目标柱z,将所有圆盘从x移到z,一次移动一个,而且不允许大的圆盘压在小的上面,会压碎,可以使用y盘进行辅助。

递归

很简短的几行代码
始终把x上所有圆盘看做两块

  • 一块是最下面的一块
  • 一块是最下面一块上面所有的
    把三个柱子设为x,y,z,一开始都在x上面。
    两块的hanoi就是直接将上面的一块移到y,下面的一块移到z,最后将y移到z

至于为何是

		hanoi(n-1,x,z,y);
		cout<<n<<"个"<<x<<"-->"<<z<<endl;
		hanoi(n-1,y,x,z);

可以看到只有中间当移动一块时是直接输出的,移动多块时是表示x借助y移到z上,因为上面是多块不是一块,不能直接移动,要借助一个空的柱子。可以借助三块的例子来向一下。
当把上面两块当成一个整体来移动,必须借助一个空的将最小的一块安置一下才能实现两块一起动。

#include<iostream>
using namespace std;
void hanoi(int n,char x,char y,char z)
{
	if(n==1)
	{
		cout<<1<<"个"<<x<<"-->"<<z<<endl;
	}
	else
	{
		hanoi(n-1,x,z,y);
		cout<<n<<"个"<<x<<"-->"<<z<<endl;
		hanoi(n-1,y,x,z);
	}
}
int main()
{
	int n;
	cin>>n;
	hanoi(n,'x','y','z');
}

不用递归

  • 任何尾递归都可以用循环来替代。
  • 不是尾递归可以使用数据结构中的栈来替代。
    -尾递归的含义
    每一个函数在使用时就相当于进栈,当return时就出栈。
    所以递归就是不断入栈,当到出口时就逐一出栈,所以递归实际上总是从出口开始执行,出口在栈顶。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct record //就像用递归里面的三个变量
{
	int n;
	char x;
	char y;
	char z;
	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;
}
bool pop(stack *stack,record *&e) //从栈顶弹出元素
{
	if(stack->num==-1)
		return false;
	stack->num--;
	e = stack->records;
	stack->records = stack->records->next;
	return true;
}

void move(int n, char x, char y, char z)
{
	stack stack = { NULL, 0 };
	record *record1, *p_record;
	//初始化栈
	record1 = (record *)malloc(sizeof(record));
	record1->n = n, record1->x = x, record1->z = z;
	record1->y = y;
	push(record1, &stack);
	//迭代开始
	while (stack.num != 0)
	{
		//取出一个元素,进行一下操作,把他相当于两块,和用递归一样。
		pop(&stack,p_record);
		if (p_record->n == 1)//这里表示当只有一块时直接输出就行了。
		{
			printf("%c->%c\t", p_record->x, p_record->z);
			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->x = p_record->x,
			record2->z = p_record->y, record2->y = p_record->z;
		record3->n = 1, record3->x = p_record->x,
			record3->z = p_record->z, record3->y = p_record->y;//n=1就可以直接移动,也就是直接输出
		record4->n = p_record->n - 1, record4->x = p_record->y,
			record4->z = p_record->z, record4->y = p_record->x;
		//出栈一个进栈三个
		push(record4, &stack);
		push(record3, &stack);
		push(record2, &stack);

		//释放内存
		free(p_record);
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	//调用move方法
	move(n, 'A', 'B', 'C');
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值