递归(基础)

news2024/11/25 17:19:19

目录

一、递归的定义

1、什么时候会用到递归的方法

1. 定义是递归的

2. 数据结构是递归的

3. 问题的解法是递归的 

2、应用递归的原则

3、递归调用顺序问题 

1. 首先递归的过程可以总结为以下几点:

2. 递归工作栈​​​​​​​

二、 递归和非递归的转化

1. 单向递归可用迭代 

举例:斐波拉契数列

 2. 尾递归可用迭代

举例:欧几里德求最大公约数

3、借助栈实现非递归

1. 举例:二叉树的先序遍历

 2. 举例:二叉树的中序遍历


一、递归的定义

  • 在数学及程序设计方法学中为递归下的定义是这样的:若一个对象部分包含地包含它自己,或用它自己来定义它自己,则称这个对象是递归的;若一个过程直接或间接的调用自己,则称这个过程为递归的过程。
  • 简而言之,递归方法就是直接或间接地调用其自身

1、什么时候会用到递归的方法

1. 定义是递归的

  • 以数学上常用的阶乘函数为例,其定义和计算都是递归的

定义:

\large n!=\begin{cases}1 & x = 0\\n(n-1)! & x > 0\end{cases}

 求解函数:

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

}

2. 数据结构是递归的

  • 链表就是一种递归的数据结构,从概念上讲,单链表可以递归的定义为一个结点,当该结点的指针域为NULL的时候,就表明此链表是一个单链表,这个结点的指针域也可以指向另一个单链表,而这个单链表具有同样的结构
  • 也可以采用递归的方式来描述。首先一棵树要么是空,要么由若干非空子树组成(子树的数目可以为空),且这些子树的根都通过一条边连到根上。每个子树同样具有这样的结构,要么为空,要么由根和若干非空子树组成。

3. 问题的解法是递归的 

2、应用递归的原则

  • 首先是必须要有一些“基本条件”能够采用非递归的方式计算得到,这是使用递归方法的重要前提。基本条件的满足意味着采用递归处理后的子问题可以直接解决时,就停止分解,而这些可以直接求解的问题就叫做递归的“基本条件”。
  • 为了使计算最终完结,任何递归调用都要朝着“基本条件”的方向进行。
  • 例1:前面所举例的阶乘
if (n == 1)
   return 1;

 这就是所谓的基本条件。

  • 例2:二分查找(折半查找) 
int BinSearch(int* data, int key,int low,int high)//折半查找
{
	if (low > high)
		return -1;
	int mid = (low + high) / 2;
	//二分查找递归的核心部分
	if (key < data[mid])
		return(data, key, low, mid - 1);//继续在data[low,mid-1]左区间查找
	else if (key > data[mid])
		return(data, key, mid + 1, high);//继续在data[mid+1,high]右区间查找
	else
		return mid;//查找成功
}
  • 其中:if(low>high)是基本条件之一,即在搜索范围内无法找到想要查找的值,表示搜索失败,递归过程也就结束了;此外,找到想要查找的值递归过程也会结束,也就是“return mid”,其对应的条件是“if(key==data[mid]”。

3、递归调用顺序问题 

1. 首先递归的过程可以总结为以下几点:

  • 递归过程在实现时,需要自己调用自己
  • 层层向下递归,退出次序正好相反
  • 主程序第一次递归调用自己为内部调用
  • 它们返回调用它的过程的地址不同

2. 递归工作栈

  • 在递归过程中,递归的执行需要一些薄记空间来记录跟踪前一个递归调用,特别对于那些有一长串递归调用的情况,在某种程度上较同等循环而言更加费时,因为薄记工作本身就要消耗一定时间。这个薄记空间就是递归工作栈
  • 同时,每一次递归调用时,需要为过程中使用的参数、局部变量等另外分配存储空间。
  • 每层递归调用需分配函数递归时的活动记录 可以用如下图表示:

 

  •  以下列代码为例:
#include<iostream>
using namespace std;
void Fuction1(int n)
{
	if (n < 4)
	{
		printf("%d\n", n);
		Fuction1(n + 1);
	}
}
void Fuction2(int n)
{
	if (n < 4)
	{
		Fuction2(n + 1);
		printf("%d\n", n);
	}
}
int main()
{
	cout << "第一个函数:" << endl;
	Fuction1(0);
	cout << "第二个函数:" << endl;
	Fuction2(0);
	return 0;
}
  • Fuction1函数的执行过程

 

  • Fuction2函数执行过程:

 

二、 递归和非递归的转化

1. 单向递归可用迭代 

  • 单向递归: 是指递归的过程总是朝着一个方向进行。斐波拉契数列的求解就是单向递归
  • 举例:斐波拉契数列

  • 递归求解斐波拉契数列: 
int Fib(int n)
{
	if (n < 2)
		return n == 0 ? 0 : 1;
	else if (n >= 2)
	{
		n = Fib(n - 1) + Fib(n - 2);
		return n;
	}
}
  •  迭代求解斐波拉契数列:
int Fib(int n)
{
	vector<int> v;
	v.push_back(0);
	v.push_back(1);
	int i = 2;
	for (i = 2; i <= n; i++)
	{
		int t = v[i - 1] + v[i - 2];
		v.push_back(t);
	}
	return v[n];
}

 

 

 2. 尾递归可用迭代

  • 尾递归函数是以递归调用作为结尾的函数,它是单向递归的特例,它的递归调用语句只有一个,而且放在过程最后。当递归调用返回时,返回到上一层递归调用语句的下一语句的时候,而这个位置正好是程序的结尾。
  • 尾递归示意图:

 

  • 举例:欧几里德求最大公约数

  • 是用较大的数除以较小的数,较小的除数和得出的余数构成新的一对数,继续做上面的除法,直到出现能够整除的两个数。
  •  递归求解最大公约数:
int gcd(int a, int b)
{
	if (b == 0)
		return a;
	else
		gcd(b, a % b);
}
  • 迭代求解最大公约数:
int gcd(int a, int b)
{
	int tmp;//保存a%b
	while (b!=0)
	{
		tmp = a % b;
		a = b;
		b = tmp;
	}
	return a;
}

3、借助栈实现非递归

1. 举例:二叉树的先序遍历

  • 递归先序遍历:
void PreOrder(BTree T)//先序遍历
{
    if (T != NULL)
    {
        cout << T->data << " ";//访问根结点
        PreOrder(T->lchild);//先序遍历左子树
        PreOrder(T->rchild);//先序遍历右子树
    }
}
  • 用栈先序遍历:
bool First(BTree T)
{
    stack<BTNode*>s;
    BTNode* p = T;
    if (p != NULL )//二叉树不为空
    {
        s.push(p);
        while (!s.empty())//栈不为空
        {
            p = s.top();
            cout << s.top()->data << " ";//先访问栈顶元素
            s.pop();//栈顶元素退栈
            if (p->lchild != NULL)
                s.push(p->rchild);//栈顶元素的右孩子结点进栈
            if (p->rchild != NULL)
                s.push(p->lchild);//栈顶元素的左孩子结点进栈
        }
    }
    return true;
}

 2. 举例:二叉树的中序遍历

  • 递归中序遍历:
void InOrder(BTree T)//中序遍历
{
    if (T != NULL)
    {
        InOrder(T->lchild);
        cout << T->data << " ";
        InOrder(T->rchild);
    }
}
  • 用栈中序遍历:
bool InOder(BTree T)
{
    stack<BTNode*>s;
    BTNode* p = T;
    while (p != NULL || !s.empty())
    {
        while (p != NULL)//当前结点不为空
        {
            s.push(p);
            p = p->lchild;
        }
        if (!s.empty())
        {
            cout << s.top()->data << " ";//访问栈顶元素
            p = s.top()->rchild;//先将栈顶元素的右孩子存储起来
            s.pop();//栈顶元素出栈
        }
    }
    return true;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Allegro如何快速把Class高亮成不同的颜色操作指导

Allegro如何快速把Class高亮成不同的颜色操作指导 在做PCB设计的时候,高亮Class组是一个非常频繁的操作,Allegro支持快速的将Class高亮成不同的颜色,并且还可以形成一个列表,如下图 具体操作如下 选择File选择Change Editor

select ( ) for update 锁行还是锁表?

select &#xff08; &#xff09; for update 锁行还是锁表&#xff1f; 一、验证 创建SQL表 //id为主键 //name 为唯一索引 CREATE TABLE user (id INT ( 11 ) NOT NULL AUTO_INCREMENT,name VARCHAR ( 255 ) DEFAULT NULL,age INT ( 11 ) DEFAULT NULL,code VARCHAR ( …

SpringCloud微服务项目实战 - 6.延迟任务

我没有失约&#xff0c;我与春风共至&#xff0c;我与夏蝉共鸣&#xff0c;我与秋叶共舞&#xff0c;我与凛冬共至&#xff0c;唯独你背道而行&#xff01; 系列文章目录 项目搭建App登录及网关App文章自媒体平台&#xff08;博主后台&#xff09;内容审核(自动)延迟任务 - 精…

JVM快速入门学习笔记(一)

参考&#xff1a; https://blog.csdn.net/m0_38075425/article/details/81627349 www.kuangstudy.com JVM 常问面试题 请你谈谈你对JVM的理解&#xff1f; java—>class---->Java8虚拟机和之前的变化更新&#xff1f;什么是OOM 内存溢出什么是栈溢出StackOverFlowErr…

Matplotlab绘制散点图小节

前言现有一堆数据&#xff0c;是散点坐标形式&#xff0c;现在需要将它们绘制成散点图&#xff0c;并解决了关于Matplotlib绘图不能显示汉字的问题。读取数据数据格式如下图。第一行为一个数字&#xff0c;表示当前文件共有多少行数据。 第二行开始为真正的数据&#xff0c;各数…

如何冻结Excel中的行

在Excel中有一个冻结行的功能。在冻结行的帮助下,我们可以固定我们选择的窗格或行,以超出特定的限制工作表。 可以从“视图”菜单选项卡的“窗口”部分的“冻结窗格”下拉列表中访问“冻结行”。首先,要冻结列,请选择要冻结的列或将光标放在该列的任何位置,然后从列表中选…

vue 使用hook 对 chekbox 做简单的逻辑抽离,一个核心多套模板

现在的组件库都会包含些相同的基础组件&#xff0c;功能大差不差&#xff0c;只是不同UI规范下的具体实现。这些基础组件基本能满足大部分的开发需求。 但世上无银弹&#xff0c;有时我们需要对组件做细微的调整可能是功能上的&#xff0c;可能是UI上的&#xff0c;例如 tab切换…

JavaWeb基础(三) Request和Response详解

JavaWeb基础(三) Request和Response详解 1&#xff0c;Request和Response的概述 Request是请求对象&#xff0c;Response是响应对象。 此时&#xff0c;我们就需要思考一个问题request和response这两个参数的作用是什么? request: 获取请求数据 浏览器会发送HTTP请求到后台…

跨站脚本攻击漏洞(XSS)-基础篇

数据来源 跨站脚本攻击 1、什么是跨站脚本攻击? 跨站脚本( Cross-site Scripting)攻击&#xff0c;攻击者通过网站注入点注入客户端可执行解析的 payload&#xff08;脚本代码&#xff09;&#xff0c;当用户访问网页时&#xff0c;恶意 payload自动加载并执行&#xff0c;…

索引(index)

索引&#xff08;index&#xff09; 1、什么是索引&#xff1a; 索引是在数据库表的字段上添加的&#xff0c;是为了提高查询效率存在的一种机制。一张表的一个字段可以添加一个索引&#xff0c;当然多个字段联合起来也可以添加索引&#xff0c;索引相当于一本书的目录&#xf…

Spring Boot 3 步完成日志脱敏,简单实用!

在我们写代码的时候&#xff0c;会书写许多日志代码&#xff0c;但是有些敏感数据是需要进行安全脱敏处理的。 对于日志脱敏的方式有很多&#xff0c;常见的有&#xff1a; 使用conversionRule标签&#xff0c;继承MessageConverter 书写一个脱敏工具类&#xff0c;在打印日志…

springboot+mybatisplus实现分页

在日常开发中&#xff0c;多记录的列表查询可能会遇到分页处理的场景&#xff0c;在springboot项目中传统是引入mybatis组件进行持久化&#xff0c;然后通过pagehelper组件进行分页实现。下面体验一下在springboot项目中引入mybatisplus组件&#xff0c;通过其自带分页插件实现…

cpu简述--指令集架构

很多初级开发者其实都对cpu了解不多&#xff0c;个人兴趣原因想要了解一下cpu的相关知识&#xff0c;所以开几篇文章记录一下吧。 2002年8月10日,中国科学院计算技术研究所的青年科学家胡伟武带领研制组,研制出我国首枚拥有自主知识产权的通用高性能微处理芯片——“龙芯一…

MindOpt安装配置教程(Windows系统)

1 前言 官网有很多的说明文档、教程&#xff0c;但是可能有些地方&#xff08;这里仅仅补充安装配置部分&#xff0c;其他操作建议自行去官网进行探索&#xff09;不是很详细&#xff0c;踩了一些坑&#xff0c;所以进行了一些总结。 2 下载安装 url&#xff1a;求解器SDK下载…

Nginx基础02:配置文件nginx.conf(Part1)

我们使用Nginx主要是通过其配置文件nginx.conf来实现的。按照一定的规则&#xff0c;编写特定的指令&#xff0c;可以帮助我们实现对Web服务的控制&#xff01;所以&#xff0c;学习Nginx的用法&#xff0c;几乎就是学习nginx.conf&#xff01;如何使用本篇文章本文作为一篇高度…

【博客590】iptables raw表的特殊作用

iptables raw表的特殊作用 1、iptables四表五链&#xff1a; 2、raw表的优先级 从上图中可以看到raw表作用于prerouting和output链&#xff0c;且在这两个链中的几个表中拥有最高优先级&#xff0c;并且是高于连接跟踪的&#xff0c;这个也是raw表用于优化性能的一个重要前提 …

Leetcode链表专题专练-万字总结

文章目录 系列&#xff1a;链表专练 语言&#xff1a;java & go 题目来源&#xff1a;Leetcode 常考点&#xff1a; 单链表 & 双链表 &双指针 思路和参考答案文章目录链表专题总结链表专练链表专题总结 链表是一种通过指针串联在一起的线性结构&#xff0c;每一个…

【计算机网络】传输层协议-------TCP详解

文章目录1. TCP 协议概述2. TCP原理2.1 保持可靠性的机制2.1.1 确认应答2.1.2 超时重传2.1.3 连接管理机制(安全机制)2.1.3.1 三次握手2.1.3.2 四次挥手2.1.4 滑动窗口2.1.5 流量控制2.1.6 拥塞控制2.1.7延时应答2.1.8 捎带应答2.1.9 粘包问题2.1.10 TCP异常2.1.11 TCP vs UDP1…

记录每日LeetCode 112.路径总和 Java实现

题目描述&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶…

马蜂窝如何利用 APISIX 网关实现微服务架构升级

作者&#xff1a;董红帅&#xff0c;马蜂窝微服务体系建设以及基础服务能力建设专家。 马蜂窝作为旅行社交平台&#xff0c;是数据驱动的新型旅行电商。基于十余年的内容积累&#xff0c;马蜂窝通过 AI 技术与大数据算法&#xff0c;将个性化旅行信息与来自全球各地的旅游产品供…