递归(五)—— 初识暴力递归之“如何利用递归实现栈逆序”

题目:要求不使用额外的数据结构,仅利用递归函数实现栈的逆序。

题目分析

利用实例来理解题意,栈内元素从栈底到栈顶一次是3,2,1 ,要求经过处理后,栈底到栈顶依次是1,2,3。

思路:

因为是用递归的逻辑去实现题目的要求,而递归之所以能够实现是因为利用了系统栈,在每一次递归函数的调用前都将“现场“保存在了系统栈中。

而我们实现题目要求,自然而然想到的逻辑就是在每次循环时都去拿栈底元素,直到栈为空时,结束从栈中取全素的操作,然后将取出的元素依次在放入栈中。例如,设:我们要操作的栈名为static_1,第一次拿到static_1的栈底元素是3 ,将它保存在系统栈中;

第二次拿到的static_1的栈底元素是2,将它保存在系统栈中;

第三次拿到的static_1的栈底元素是1,将它保存在系统栈中;

第四次,栈static_1已经空了,结束取元素操作,接下来将系统栈的元素存入栈中。

系统栈的栈顶是1,存入栈static_1中;

系统栈的栈顶是2,存入栈static_1中;

系统栈的栈顶是3,存入栈static_1中;

根据这个思路,我们写出代码:

//代码段1
#include <stack>
using std::stack;//将栈stack_1中元素逆序反转;
void reverse(stack<int>& stack_1){if(stack_1.empty()){ //如果栈为空,退出return;}else{int last= getLast(stack_1); //获取static_1中的栈底元素reverse(stack_1);stack_1.push(last)}
}

我们将系统栈画出,体会递归过程:

注:函数getLast 是用来实现获得栈底函数。

第一步:当首次调用reverse函数:

因为  stack_1.empty() ==  false, 所以程序继续运行到 12行, 为遇到函数调用,保存现场到系统栈:

第二步:第二次进入reverse(2), 因为 stack_1.empty() ==  false, 程序运行到11行,得到last = 2, 运行到12行时遇到递归函数调用,保存现场到系统栈。程序再次进入reverse(stack_1)  

              

第三步:第三次进入reverse(3), 因为 stack_1.empty() ==  flase, 程序运行到11行,得到last = 1, 运行到12行时遇到递归函数调用,保存现场到系统栈。程序再次进入reverse(stack_1)

            

第四步:第四次进入reverse(4), 因为 stack_1.empty() == true, 直接退出函数reverse(4)。

第五步,程序检查当前系统栈的情况,进入reverse(3),继续执行第13行代码 stack_1.push(last),将last = 1写入stack_1,退出 reverse(3);

第六步:程序检查当前系统栈,进入reverse(2), 继续执行第13行代码,将last = 2写入stack_1;退出reverse(2);

第七步:程序检查当前系统栈,进入reverse(1),继续执行第13行代码,将last = 1写入stack_1, 退出reverse(1); 此时系统栈为空,程序执行完毕。

关键问题解决

问题分析到这里,我们对如何利于系统栈实现给定栈结构stack_1中的元素逆序存储已经有了明确的实现思路,但是还有一个关键函数没有实现,即如何获得栈底元素,函数getLast 的函数体。

对于这个函数,规定的已知条件依然是不借助其他数据结构。在reverse函数中,getLast 函数是被看作一个黑盒函数来使用的,即每次调用都是返回的栈底元素,下面我们来分析它的内部逻辑。 

因为最终的实现效果是:每执行一次getLast,栈底元素被取出(函数返回),栈内其它元素依次盖下来。如图:

  代码实现

int getLast(stack<int>& stack_1){int last = stack_1.top();if(stack_1.empty()){return last;}else{int result = getLast(stack_1);stack_1.push(result);return result;}
}

代码分析 :

利用系统栈分析递归调用过程。

第一步:result= stack_1.top() == 1;

              stack_1.empty() == false; 所以代码执行到第7行;保存现场到系统栈; 

第二步:程序进入getLast(stack_1{2,3});

               result = stack_1.top() == 2;

               stack_1.empty() == false; 所以代码执行到第7行;保存现场到系统栈;

 第三步:程序进入getLast(stack_2{3});

                result = stack_1.top() == 3;

                stack_1.empty() == true;  程序返回 3;

 第四步:程序检查系统栈,进入getLast(stack_1{3}),  将返回值赋给last, 即last = 3;

               继续线下执行到8行, 将result == 2 写入stack_1;程序执行到第9行,即返回值为3.

销毁函数getLast(stack_1{3})的调用过程:

第五步:程序检查系统栈,进入getLast(stack_1{2,3}), 将返回值赋给last, 使last = 3, 程序继续执行到第8行,将result= 1 写入stack_1, 执行第9行,函数返回last值,并且销毁getLast(stack_1{2,3})的调用过程。

此时:stack_1为:

     函数返回值为3。

运行结果:

将代码补充完整,并验证。

#include <stack>
#include <iostream>void print(string str, stack<int> stack) {std::cout << str;while (stack.size()) {std::cout << stack.top() << " ";stack.pop();}std::cout << std::endl;
}//给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数,如何实现
//栈底元素移除掉,上面的元素盖下来,返回移除的元素int getLast(stack<int>& s) {int result = s.top();s.pop();if (s.empty()) {return result;}else {int last = getLast(s);s.push(result);return last;}
}//如何利用递归实现栈逆序?
void reverse(stack<int>& stack) {if (stack.empty()) {return;}int i = getLast(stack);reverse(stack);stack.push(i);
}int main() {stack<int> stack_1;stack<int> stack_2;stack_1.push(3);stack_1.push(2);stack_1.push(1);stack_2.push(3);stack_2.push(2);stack_2.push(1);print("栈内原始值:", stack_2);auto fun = [](stack<int >& stack_1) {if (stack_1.size() == 0) return;reverse(stack_1);};fun(stack_1);print("执行了逆序后:", stack_1);return 0;
}

运行结果:

Tip:

在编写代码时,要注意函数参数的类型:引用参数类型的使用。

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

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

相关文章

OpenCV中使用Canny算法在图像中查找边缘

操作系统&#xff1a;ubuntu22.04OpenCV版本&#xff1a;OpenCV4.9IDE:Visual Studio Code编程语言&#xff1a;C11 算法描述 Canny算法是一种广泛应用于计算机视觉和图像处理领域中的边缘检测算法。它由John F. Canny在1986年提出&#xff0c;旨在寻找给定噪声条件下的最佳边…

NAS免费用,鲁大师 AiNAS正式发布,「专业版」年卡仅需264元

7月10日&#xff0c;鲁大师召开新品发布会&#xff0c;正式发布旗下以“提供本地Ai部署和使用能力以及在线NAS功能”并行的复合软件产品&#xff1a;鲁大师 AiNAS。 全新的鲁大师 AiNAS将持续满足现如今大众对于数字化生活的全新需求&#xff0c;将“云存储”的便捷与NAS的大容…

Power BI DAX常用函数使用场景和代码示例

Power BI函数表达式对于没有接触过的朋友可能会有些迷茫&#xff0c;花一点时间了解一下原理在学习一些常用的DAX函数&#xff0c;就可以解决工作中绝大部分问题&#xff0c;函数使用都是共同的。 以下是一些最常用的DAX函数&#xff0c;如聚合&#xff0c;计数&#xff0c;日期…

了解劳动准备差距:人力资源专业人员的战略

劳动准备差距是一个紧迫的问题&#xff0c;在全球人事部门回应&#xff0c;谈论未开发的潜力和错过的机会。想象一下&#xff0c;人才和需求之间的悬崖之间有一座桥&#xff0c;这促使雇主思考&#xff1a;我们是否为员工提供了足够的设备来应对未来的考验&#xff1f; 这种不…

【昆工主办|7月昆明】第三届绿色建筑、土木工程与智慧城市国际会议(GBCESC 2024)

随着全球城市化进程的加速&#xff0c;绿色建筑、土木工程与智慧城市等议题逐渐成为了行业内外关注的焦点。在这一背景下&#xff0c;第三届绿色建筑、土木工程与智慧城市国际会议&#xff08;GBCESC 2024&#xff09;的召开&#xff0c;无疑将为相关领域的研究者、学者及从业者…

windows防火墙端口设置

PS&#xff1a;本文实例为Windows Server 2019&#xff0c;其他Windows版本大同小异。 1、首先打开windows防火墙&#xff0c;点击“高级设置” 2、 高级设置界面 3、假设需要开放一个端口为3306应该怎么做 光标对准“入站规则”右键新建规则&#xff0c;选择“端口” 协议这…

解决Anaconda下载pytorch常见问题

1.问题一 安装完Anaconda后&#xff0c;输入conda命令&#xff0c;出现 conda不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 分析原因&#xff1a;未配置环境到系统变量 解决方法&#xff1a;将Anaconda安装路径和Anaconda目录下的Scripts文件的路径配…

从重庆元宇宙国风秀看未来元宇宙发展趋势

2024年2月24日&#xff0c;为纪念梅兰芳先生诞辰130周年&#xff0c;以“新国风东方美”为主题的【承华灵境】元宇宙国风秀在重庆市人民大礼堂发布。这场活动将中国经典艺术与数字化技术融合&#xff0c;呈现了一场新国风东方美学的跨越时空人文科技之旅&#xff0c;其中的重点…

短链接服务Octopus-搭建实战

[WARNING] The POM for cn.throwx:octopus-contract:jar:1.0-SNAPSHOT is missing, no dependency information available 解决方案&#xff1a; cd octopus-contract/ mvn install -------------- ➜ octopus-server git:(master) ✗ mkdir -p /data/log-center/octopus/s…

c++ 多边形 xyz 数据 获取 中心点方法

有需求需要对。多边形 获取中心点方法&#xff0c;绝大多数都是 puthon和java版本。立体几何学中的知识。 封装函数 point ##########::getCenterOfGravity(std::vector<point> polygon) {if (polygon.size() < 2)return point();auto Area [](point p0, point p1, p…

什么是量化机器人?它能来作些什么?一篇文章带你了解!

在科技日新月异的今天&#xff0c;我们经常会听到一些听起来高大上的词汇&#xff0c;比如“人工智能”、“大数据”和“量化交易”。而在这其中&#xff0c;“量化机器人”更是一个让人既好奇又略感神秘的存在。今天&#xff0c;我们就用通俗易懂的语言&#xff0c;一起来揭开…

网页UI:想让页面更加精致,我来偷偷告诉你7个细节

采用合适的配色方案&#xff1a; 选择一套合适的配色方案&#xff0c;搭配主题色和辅助色&#xff0c;以及不同色调的阴影和渐变效果&#xff0c;可以让网页UI更加丰富、有层次感。 使用合适的字体&#xff1a; 选择适合网页风格的字体&#xff0c;如清晰易读的无衬线字体&a…

Java中的公平锁和非公平锁

1、什么是公平锁和非公平锁 公平锁和非公平锁是指在多线程环境下&#xff0c;如何对锁进行获取的顺序和策略的不同。 公平锁是指多个线程按照申请锁的顺序来获取锁&#xff0c;即先到先得的策略。当一个线程释放锁之后&#xff0c;等待时间最长的线程将获得锁。公平锁的优点是保…

【SVN-CornerStone客户端使用SVN-多人开发-解决冲突 Objective-C语言】

一、接下来,我们来说第三方的图形化界面啊, 1.Corner Stone:图形化界面,使用SVN, Corner Stone的界面,大概就是这样的, 1)左下角:是我们远程的一个仓库, 2)右上角:是我们本地的一些东西, 首先,在我的服务器上,再开一个仓库,叫做wechat, 我在这个里边,新建…

[leetcode]partition-list 分隔链表

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:ListNode* partition(ListNode* head, int x) {ListNode *smlDummy new ListNode(0), *bigDummy new ListNode(0);ListNode *sml smlDummy, *big bigDummy;while (head ! nullptr) {if (head->val &l…

柔性测斜仪:监测钻孔位移的核心利器

柔性测斜仪&#xff0c;作为一款创新的测量工具&#xff0c;凭借其卓越的设计与性能&#xff0c;在地下建筑、桥梁、隧道及水利水电工程等领域展现出非凡的应用价值。其安装便捷、操作简便、高精度及长寿命等特性&#xff0c;使之成为监测钻孔垂直与水平位移的理想选择。以下是…

32 华三vlan案例+STP

32 华三vlan案例STP 1 开启STP 显示根桥信息 查看stp中的接口角色 查看设备的根桥ID 最小的值是根网桥 原则一 网络初始化时&#xff0c;网络中所有的STP设备都认为自己是“根桥”&#xff0c;根桥ID为自身的设备ID。通过交换BPDU&#xff0c;设备之间比较根桥ID&#xff0c;网…

IEEE TETCI | GPBT: 基于种群的强化学习超参优化的学习

一、 超参数优化 超参数优化是在机器学习和深度学习中非常重要的一个环节。 超参数是在模型训练之前就需要设定的参数&#xff0c;它们不能通过训练过程自动学习得到&#xff0c;例如学习率、层数、节点数、正则化参数等。 常见的超参数优化方法包括手动搜索、随机搜索、网格搜…

如何用Vue3和Plotly.js绘制交互式瀑布图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 Plotly.js 在 Vue 中创建瀑布图 应用场景 瀑布图广泛用于可视化财务报表和展示增量变化&#xff0c;例如利润表、现金流量表和收入分析。它们通过将正值和负值堆叠在垂直轴上&#xff0c;清晰地展示每个…

从零开始学量化~Ptrade使用教程(四)——股票普通买卖与回购业务

股票普通买卖 股票买入 通过选择委托方向实现股票的买入与卖出&#xff0c;可根据输入的价格自动查询可买数量。 用鼠标点击【买入】&#xff0c;如图所示&#xff1a; 输入股票代码并选中后&#xff0c;选择委托类型&#xff0c;若为限价类型&#xff0c;输入委托价格&#xf…