递归之原理及汉罗塔的递归与非递归实现[通俗易懂]

递归之原理及汉罗塔的递归与非递归实现[通俗易懂]递归章节一.什么是递归递归:简单的讲,就是定义一个过程或函数时出现调用本过程或本函数就称为递归。典型的例子:求阶乘:intfun(intn){ if(n==1) return(1);elsereturnfun(n*fun(n-1));}二.那么使用递归需要满足那些条件呢?(1) 从上例就可以看出,递归需要终止递归的结束条件。(2)…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

递归章节

一.什么是递归

递归:简单的讲,就是定义一个过程或函数时出现调用本过程或本函数就称为递归。
典型的例子:
求阶乘:

int fun(int n) { 
   
	if(n == 1)
		return(1);
   else
        return fun(n*fun(n - 1));
}

二.那么使用递归需要满足那些条件呢?

(1) 从上例就可以看出,递归需要终止递归的结束条件。
(2) 递归的次数必须是有限次的
(3) 可以将一个大的问题转化为一个或多个与原问题相似规模较小的子问题,而这些小问题求解方法与原问题相同。

三.可使用递归的一些情况:

1. 函数或过程定义是递归的。

如,Fibonacci数列:

int Fib(int n) { 
   
	if(n == 1 || n == 2)
		return (1);
    else
        return (Fib(n - 1) + Fib(n - 2));
}

2 问题求解方法是递归的

如,汉罗塔问题:

  1. 首先定义函数:Hanio(n,x,y,z) 表示将x上的n个盘子借助y移动到z上;
    将1这个问题分解:
    (1)想要把n个盘子从x移动到z,也就是需要把n-1个盘子从x借助z先移动到y上, 即:Hanio(n-1,x,z,y)
    (2) 此时x上只有第n个盘子,直接移动到z上,即:move(n,x,z)
    (3)递归调用,Hanio(n-1,y,x,z)
    注解: 事实上,这个很好理解,相信第一步和第二步很容易理解,第三步递归调用咋回事呢?
    我们定义的函数体是Hanio(n,x,y,z) 执行完第(1)、(2)之后变成什么结果呢?
    即:y这根柱子现在有n-1个盘子,z上是第n盘子,x没有盘子。
    此时我们将 n-1赋值给n,将y赋值给x,将z赋值给z不就是和初始化状态一模一样啦,只是少了一个盘子而已,我们调用函数重复第(1)、(2)步骤就OK了。即调用Hanio(n-1,y,x,z),现在是不是懂了啊!递归始终是将大规模问题简化,并且简化后的子问题和原问题求解方法相同。源代码如下:
void Hanio(int n, char x, char y, char z)
{ 
   
	if (n == 1)
		printf("第%d个盘子:%c-->%c\n", n, x, z); 
	else { 
   
		Hanio(n - 1, 'x', 'z', 'y');   // 此时x=x,y=y,z=z
		printf("第%d个盘子:%c-->%c\n", n, x, z);
		Hanio(n - 1, 'y', 'x', 'z');   //此时 x=y,y=z,z=z
	}
}

四.递归模型:

递归模型一般分为两部分:递归结束出口和递归体。在递归体过程中,一般分为两部分,对递归问题分解和求值两部分。
如 阶乘递归:以fun(5)为例
5的阶乘分解和求解过程Alt

递归模型的一般步骤:

(1) 首先,在大问题(第n个问题)假设合理的小问题(第n-1个问题)
(2) 确定n与n-1之间的关系,也就是确定递归体。
(3) 找到合理的出口,如n=0或者n=1时的解。

五.递归与栈

用栈来实现汉罗塔:

#include<stdio.h>
#include<iostream>
#include<cstdlib>
using namespace std;
#define Max 50
typedef struct { 
   
	int n;  //表示有多少个盘子
	char x;
	char y;
	char z;
	bool move_flag;  //表示这个元素是否可以移动。 当n=1时是可以移动的
}ElemType;

typedef struct { 
   
   ElemType data[Max];
   int top;
}StackHanio;

//初始化栈
void InitStack(StackHanio &s) { 
   
	s.top = -1;
}

//判断栈是否为空
bool Stackempty(StackHanio s){ 
   
	return(s.top == -1);
}

//元素入栈
void Push(StackHanio &s, ElemType e) { 
   
	if (s.top == Max - 1)
		exit(1);
    else{ 
   
		s.top++;
		s.data[s.top] = e;
 }
}

//元素出栈
void Pop(StackHanio &s, ElemType &e) { 
   
	if (s.top == -1)
		exit(1);
	else { 
   
		e = s.data[s.top];
		s.top--;
	}
}
void Hanio(int n1, char x, char y, char z) { 
   
	StackHanio s;
	InitStack(s);
	ElemType e, e1, e2, e3;
	e.x = 'X', e.y = 'Y', e.z = 'Z', e.n = n1, e.move_flag = false;
	Push(s, e);
	while (!Stackempty(s)) { 
   
		Pop(s,e);
		if (e.move_flag == false) { 
   
			e3.n = e.n - 1, e3.x = e.y, e3.y = e.x, e3.z = e.z;
			if (e3.n == 1)
				e3.move_flag = true;
			else
				e3.move_flag = false;
			Push(s, e3);      //相当于Hanio(n-1,y,x,z)
			e2.n = e.n, e2.x = e.x, e2.y = e.y, e2.z = e.z,e2.move_flag=true;
			Push(s, e2);     //mov(n,x,z)
			e1.n = e.n - 1, e1.x = e.x, e1.y = e.z, e1.z = e.y;
			if (e1.n == 1)
				e1.move_flag = true;
			else
				e1.move_flag = false;
			Push(s, e1);    //Hanio(n-1,x,z,y)
		}
		else
		     cout << "第" <<e.n<<  "个盘片:" <<e.x<< "-->" << e.z << "\n";
	}
}
int main() { 
   
     Hanio(3, 'X', 'Y', 'Z');
	 system("pause");
	 return 0;
}

[注]: 如果我们用递归实现汉罗塔时:
将x上n个盘子借助y移动到z上
一般有以下三步:
(1)Hanio(n-1,x,z,y)
(2)mov(n,x,z)
(3)Hanio(n-1,y,x,z)
若使用栈时:由于栈是后进先出这种特性;
所以在代码实现时与递归实现的(1)和(3)反过来啦,请读者自行体会:
Alt

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/182998.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于OpenCv的人脸识别(Python完整代码)

    基于OpenCv的人脸识别(Python完整代码)目前人脸识别有很多较为成熟的方法,这里调用OpenCv库,而OpenCV又提供了三种人脸识别方法,分别是LBPH方法、EigenFishfaces方法、Fisherfaces方法。本文采用的是LBPH(LocalBinaryPatternsHistogram,局部二值模式直方图)方法。opencv是一个开源的的跨平台计算机视觉库,内部实现了图像处理和计算机视觉方面的很多通用算法,对于python而言,在引用opencv库的时候需要写为importcv2。其中,cv2是opencv的C++命名空间名称

    2022年6月7日
    51
  • 【SG90模拟舵机控制及PCA9685模块的使用】[通俗易懂]

    【SG90模拟舵机控制及PCA9685模块的使用】[通俗易懂]一.模拟舵机控制1.简介9g模拟舵机在市面上十分常见,价格也比较便宜。可用于航模,机器人或智能小车等。如上图所示,一个舵机有三条线:VCC、GND和信号线。只要通过信号线给予规定的控制信号即可实现舵机码盘的转动。2.控制信号对于此种模拟舵机的控制是通过发送PWM。…

    2025年8月10日
    5
  • 智慧小区解决方案ppt_智慧小区简介

    智慧小区解决方案ppt_智慧小区简介智慧小区项目遇到的问题汇总&解决参考跨域问题mybatisplus操作问题git操作问题跨域问题前端使用vue脚手架搭建项目,后端使用springboot+MySQL,首当其冲的问题是两者不能使用同一个端口启动,这就涉及到跨域操作。事实上,第一步,要在vue项目中的vue.config.js里添加//跨域parallel:require(‘os’).cpus().length>1,pwa:{},devServer:{port:8081,

    2022年10月17日
    3
  • 次世代3A游戏开发将飙至1.5亿美元,游戏时长将更短

    次世代3A游戏开发将飙至1.5亿美元,游戏时长将更短即将翻过的这个世代,是大作的时代,涌现了一大批的大作,譬如《荒野大镖客2》、《GTA5》、《巫师3》等游戏。当然也是预算高涨、不断跳票和开发商经常加班加点的时代。随着PS5和XSX即将到来,随之一起的将是有史以来细节最丰富和预算更贵的游戏世界,问题就出现了:游戏行业还会继续痴迷于这么庞大世界的游戏吗?在GameBabLive会议上,SIE前总裁ShawnLayden表达了对次世代游戏开发成本倍增的担忧。他认为次世代3A游戏的开发将不可避免地从今天的8000万美元飙升至1.5亿美元。因此Lay

    2022年6月10日
    78
  • 联想笔记本电脑的F1至F12键盘问题。怎么设置才能不按FN就使用F1「建议收藏」

    联想笔记本电脑的F1至F12键盘问题。怎么设置才能不按FN就使用F1「建议收藏」在BIOS中有相应调整开关,开机时进入BIOSCONFIGKeyboard/MouseChangeto"f1-f12keys"选项设置为Legacy。完成后保存重启就

    2022年8月1日
    4
  • stringutils类_emptystring

    stringutils类_emptystring本文整理匯總了Java中com.baomidou.mybatisplus.toolkit.StringUtils.isNotEmpty方法的典型用法代碼示例。如果您正苦於以下問題:JavaStringUtils.isNotEmpty方法的具體用法?JavaStringUtils.isNotEmpty怎麽用?JavaStringUtils.isNotEmpty使用的例子?那麽恭喜您,這裏精選…

    2022年10月6日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号