递归过程中语句执行顺序

递归的两种模式

模式一

//递归的过程中在"递"的过程中解决问题
function function_name(Max_argument){if(end_condition){end;}else{solve;function_name(Min_argument);//问题规模逐渐减小}
}

注:位于递归函数前的语句和函数具有顺序性

模式二

//递归的过程中在"归"的过程中解决问题
function function_name(Max_argument){if(end_condition){end;}else{function_name(Min_argument);//问题规模逐渐减小solve;}
}

注:位于递归函数后的语句的执行顺序与原顺序相反;
每一级的递归调用都拥有自己当前的局部变量,所以当调用对象的时候应该注意是调用对象的非引用(复制对象), 以避免修改子对象造成对主问题的影响

调用栈

调用栈:描述函数之间的调用关系,当函数之间相互调用的时候会使用调用栈;
调用栈由多个栈帧组成,每个栈帧记录着一个未运行完的函数; 栈帧中保存着该函数的返回地址以及局部变量;
在递归中,递归函数的每一次的”递进去”,栈帧都会将上个函数的返回地址局部变量保存以便在返回的过程中找得到相应的”回归出来的方向”

通过一个简单的例子说明上述调用顺序问题

//10进制转2进制
void f(int n){if(n==0)return;printf("%d",n%2);//模式1,该模式下输出语句将会是顺序调用f(n/2)
}
//n=4,将输出001,整个过程中先调用printf语句,然后"递进去",通过栈帧进行回归操作最终返回至main函数void f(int n){if(n==0)return;f(n/2)printf("%d",n%2)
//模式2,整个过程中先执行f 函数进行递归,到达递归基时返回执行printf
//整个过程中就是通过栈帧来记录返回过程应该执行的printf,形成"回归出来"解决问题,最终返回至main函数
//n=4,输出100
}

接下来将用斐波那契查找作为典型的例子证明尾递归的重要性:
看下面的一个错误的例子:

#include<iostream>
using namespace std;
int find(int a[],int lo,int hi,int e){int mid=(hi+lo)/2;if(e==a[mid]) return mid;if(e<a[mid]) {cout<<"lo_1="<<lo<<endl;find(a,lo,mid-1,e);}if(e>a[mid]){ find(a,mid+1,hi,e);cout<<"lo_2="<<lo<<endl;}if(lo>hi) {cout<<"lo_3="<<lo<<endl;return 0;  }} 
int main(){//0,1,2,3,4,5,6,7,8,9 ,10,11,12,13,14,15,16,17 int a[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18};cout<<find(a,0,17,18);return 0;
}
//斐波那契查找
这个例子证明了尾递归的重要,当前出现的问题是在递归过程中返回值具有随机性,为正确将值返回,记住一条
//递归过程中栈帧的调用,到达递归基的时候返回出正确结果,但是经过栈帧的调用后,正确的返回值返回给上一层调用函数,上一层函数中未寻找到正确的值
//无法返回出正确的值,则返回出去一个随机的值,导致最后答案错误, 正确的做法是将递归过程改为尾递归(return find(....)),直接终止程序(将后续的语句执行停止)
//就此返回出去的值只能是递归基时产生的值(每一层程序终止后所对应的栈帧被清除,最后只保留着递归基中的栈帧) 
//原本打算采用else处理,不用return改为尾递归,但是失败了,因为栈栈的缘故,每层的栈帧未清除,并且返回过程中没有满足条件的语句导致没有返回值,最终无法
//完成尾递归的操作 
//唉, 理解了递归过程,但是还未深刻理解尾递归的含义,莫大的悲哀,导致出现不该出现的错误 

针对上述的操作进行修改

//斐波那契查找
/* 
#include<iostream>
using namespace std;
int f[]={0,1,1,2,3,5,8,13,21,34}; 
//       0 1 2 3 4 5 6 7 8 9 10 
int find(int a[],int lo,int hi,int e){int k=0;while((hi-lo)>f[k]) {//斐波那契数列确定当前的黄金分割点k++;//  cout<<"k"<<k<<endl;} int mid=lo+f[k-2]-1;//在中点求值出现错误,未正确表示中点位置 
//  int mid=(lo+hi)>>1; if(lo>=hi) {return 0;}//未命中目标if(e==a[mid]) return mid;if(e<a[mid]) {return    find(a,lo,mid-1,e);}if(e>a[mid]) {return    find(a,mid+1,hi,e);}
} 
int main(){//0,1,2,3,4,5,6,7,8,9 ,10,11,12,13,14,15,16,17 int a[]={1,2,3,4,5,6,7,8,9};cout<<find(a,0,9,8);return 0;
} 

递归过程调用栈的使用与调用其他函数没有区别,每一次的函数调用将会形成新的栈帧以保存上一次函数的返回地址和局部变量, 当栈帧中函数体执行完成时将会删除栈帧,处理返回值并修改当前代码行
来自别人的话_很赞同__递归函数尽量不要有返回值或者基本类型的返回值(直接尾递归),如果要求必须有复杂类型返回值,写成两个函数,递归函数不要有返回值,只是在函数中改变复杂类型的值;在驱动程序中定义复杂类型,调用递归函数返回复杂类型

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

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

相关文章

qq面板(仿版,未完待续中。。。。)---2017-04-24

主要实现效果&#xff1a; 1、点击对话&#xff0c;显示对话&#xff1b;点击联系人&#xff0c;显示联系人 2、在联系人界面&#xff1a; 实现好友列表的展开与折叠&#xff1b;&#xff08;图12&#xff09; 实现鼠标移到好友列表上的背景颜色的变化&#xff1b;&#xff08;…

苹果企业证书_苹果签名经常掉签原因大汇总

苹果签名就是数字签名&#xff0c;是基于非对称加密算法来实现的&#xff0c;对称加密就是通过非对称加密算法实现的&#xff0c;对称加密是通过同一份秘钥加密解密数据&#xff0c;非对称加密有两份秘钥&#xff0c;分别是公钥和私钥&#xff0c;用公钥进行加密的数据只能使用…

漫画|Linux 并发、竞态、互斥锁、自旋锁、信号量都是什么鬼?

1. 锁的由来&#xff1f;学习linux的时候&#xff0c;肯定会遇到各种和锁相关的知识&#xff0c;有时候自己学好了一点&#xff0c;感觉半桶水的自己已经可以华山论剑了&#xff0c;又突然冒出一个新的知识点&#xff0c;我看到新知识点的时候&#xff0c;有时间也是一脸的懵逼…

C++_顺序容器

顺序容器类型 顺序容器 vector: 支持快速随机访问list: 支持快速插入与删除deque: 双端队列 顺序适配器 - stack: 后进先出(LIFO)堆栈 - queue: 先进先出(FIFO)队列 - priority_queue: 有优先级管理的队列 上述顺序容器包含于以下头文件中:< vector >,< list &…

python画tan_Python入门之三角函数tan()函数实例详解

描述tan() 返回x弧度的正弦值。语法以下是 tan() 方法的语法:import mathmath.tan(x)注意&#xff1a;tan()是不能直接访问的&#xff0c;需要导入 math 模块&#xff0c;然后通过 math 静态对象调用该方法。参数x -- 一个数值。返回值返回x弧度的正弦值&#xff0c;数值在 -1 …

课程作业一

由于代码的难点部分是王源写的。。所以开始我选择了重写。。但是重写好像比我想象的复杂太多&#xff0c;加上时间分配不够所以现在还没有完成。。先提交随笔写好后补上代码。。我道歉认罚。。把这次当成一个教训。。 转载于:https://www.cnblogs.com/daydreams/p/6759372.html…

不废话~就是抽奖~

不废话就是抽奖 在公众号回复-抽奖- 获取抽奖二维码参与抽奖

C++关联容器总结一

关联容器 关联容器: 通过键(key)储存与读取元素 顺序容器: 通过元素在容器中的位置顺序储存,访问 关联容器类型 map 关联数组&#xff1a;元素通过键来存储和读取 set 大小可变的集合&#xff0c;支持通过键实现的快速读取, 具有集合的性质 multimap 支持同一个键多次出现…

威纶触摸屏与电脑连接_PLC与这7种设备的连接方式,一看就懂!

点击上方电工小青年&#xff0c;关注并星标专业的电工电气领域自媒体&#xff0c;不容错过欢迎转发朋友圈~PLC常见的输入设备有按钮、行程开关、接近开关、转换开关、拨码器、各种传感器等&#xff0c;输出设备有继电器、接触器、电磁阀等。正确地连接输入和输出电路&#xff0…

okHttp源码解析------待续

看该篇文章前首先要熟悉okHttp的使用&#xff0c;建议先读OkHttp的简单使用 本文的源码解析参考链接&#xff1a;okhttp3总和解析 1.从URL请求处理开始分析 由异步将请求加入调度方法开始引入正题&#xff1a; getClient().newCall(request).enqueue(new Callback() {Overridep…

Android studio JNI jni实例

1.Jni的作用 1.Jni的作用 Java是一种比较高级的语言&#xff0c;Java调用c库&#xff0c;调用c库是必不可少的&#xff0c;所以Jni就应运而生了。看了这个文章的同学&#xff0c;应该能够自己写个APK装在自己的手机里面吧&#xff0c;以前刚开始做android的时候&#xff0c;写…

二叉树先序遍历,中序遍历,后序遍历,层次遍历学习总结及完整C/C++代码

伪代码阐述 先序遍历 先序遍历:先访问根节点, 然后深入左子树,直到不能深入时再深入右子树 由定义可得递归式 void travPre_R(BinNodePosi* x,VISIT& visit){if(!X) return; //到达叶子节点,开始回归visit(x->data);//向左子树深入的过程中便开始进行对每个节点的数据…

nedc工况_东南DX3 EV续航升级 NEDC综合工况续航451公里

东南DX3 EV续航升级版车型曝光&#xff0c;电池系统能量密度由之前的141Wh/kg提升至了161Wh/kg&#xff0c;NEDC综合工况续航也由老款产品的351km提升至了451km。近日&#xff0c;工信部公布了2019年第7批《新能源汽车推广应用推荐车型目录》&#xff0c;东南DX3 EV续航升级版车…

不笑找我系列 | 程序员爆笑漫画十条

原创翻译~ 转载请说明出处~~~~~~~~ 1、如果你让码农给你做个事情&#xff0c;比如修个灯泡&#xff0c;他会这样去执行你的指令 2、分享一个码农发现并解决bug的过程&#xff0c;实在是符合我们码农的人设 3、码农的一天&#xff0c;像极了我的一天 4、至今为止&#xff0c;没…

AVL树学习总结

AVL树 平衡二叉树的缺点 由于平衡二叉搜索树的search(), insert(),remove()接口的运行时间与二叉树的高度成正比,所以若不能有效控制树高, 从平均复杂度来看,二叉平衡搜索树并不能让人满意 理想平衡 二叉树的性能取决于树的高度,只有当左右子树的高度接近时才能达到理想平衡…

nginx编译安装_Nginx编译安装nginx-upsync-module模块以实现动态负载

安装依赖包OpenSSL在官网下载页下到最新稳定版1.0.2q。PCRE在 PCRE 官网可以找到下载地址&#xff0c;这里选择8.x的最高版本 pcre-8.42.tar.gz。zlibzlib 直接选择官网首页最新的zlib-1.2.11.tar.gz。下载nginx 源码包及nginx-upsync-module模块源码这里下载的是nginx稳定版ng…

centos7 qt之程序编译 cant start process “cmake”

之所以出现这个问题&#xff0c;是由于qt内置的cmake与系统已安装的cmake命令冲突。解决的方法是&#xff0c;在build里将cmake命令加上绝对路径。 问题得以解决。转载于:https://www.cnblogs.com/jiu0821/p/6762343.html

码农笑话图片十张

原创翻译~转载请说明出处~~~~~~~~1、如果你让码农给你做个事情&#xff0c;比如修个灯泡&#xff0c;他会这样去执行你的指令2、分享一个码农发现并解决bug的过程&#xff0c;实在是符合我们码农的人设3、码农的一天&#xff0c;像极了我的一天4、至今为止&#xff0c;没有遇到…

伸展树学习总结

伸展树 与AVL树类似, 伸展树也是二叉搜索树的一种形式, 伸展树无需保证时刻保持全树的平衡,也不需要像AVL树一样要求记录平衡因子的附加信息 伸展树的提出源于信息访问的局部性(刚被访问过的信息有可能再次被访问,要被访问的元素可能位于刚访问过的元素的附近), 就伸展树而言…

python的if和else、for、while语法_python-变量、if else语句 、for循环、while循环(4月26号)...

变量&#xff1a;五&#xff0e;注意&#xff1a;python是可执行程序 在linux写python第一行必须写#!/usr/bin/env python(声明解释器在windows中写python第一行需要写# -*- coding:utf-8 -*-Pycharm:开发调试效率高 在pycharm中new project 并且每天创建一个目录右键diectory…