利用栈将递归转换为非递归

对于一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化,可直接写出相应的非递归算法。

步骤

第一次调用的参数push进堆栈,原有递归代码外层加一个while循环,判断条件就是递归结束的条件。递归调用的地方改成push(); continue;
直到遇到递归终止条件,退出递归运算所在循环,再用一个新的循环做出栈操作并计算,将递归代码中的return改成pop并执行响应的计算,直到栈空为止。就可以了。

完整描述:

(1) 设置一个工作栈存放递归工作记录(包括实参、 返回地址及局部变量等)。

(2) 进入非递归调用入口(即被调用程序开始处) 将调用程序传来的实参和返回地址入栈(递归程序不可以作为主程序,因而可认为初始是被某个调用程序调用。

(3) 进入递归调用入口:当不满足递归结束条件时,逐层递归,将实参、 返回地址及局部变量入栈,这一过程可用循环语句来实现一模拟递归分解的过程

(4) 递归结束条件满足,将到达递归出口的给定常数作为当前的函数值。

(5) 返回处理:在栈不空的情况下,反复退出栈顶记录,根据记录中的返回地址进行题意规定的操作,即逐层计算当前函数值,直至栈空为止一模拟递归求值过程。

通过以上步骤,可将任何递归算法改写成非递归算法。但改写后的非递归算法和原来比较起来,结构不够清晰,可读性差,有的还需要经过一系列的优化。

代码示例

设 n 为大于等于 0 的整数,利用堆栈设计下列函数的非递归算法。(天津大学,2006)

下面将给出一种递归解法、四种非递归解法,供参考。

import java.util.Stack;public class Recursion {public static void main(String[] args) {// 测试用例for (int i = 0; i < 20; i++) {System.out.println(recursion(i));System.out.println(non_recursion1(i));System.out.println(non_recursion2(i));System.out.println(non_recursion3(i));System.out.println(non_recursion4(i));System.out.println("=====");}}/*** 使用递归*/public static int recursion(int n) {if (n == 0) {return 1;} else {int b = n / 2;int res = recursion(b);return n * res;}}/*** 非递归方法1:利用栈,双参数*/public static int non_recursion1(int n) {class Node {int a;int b;}Stack<Node> stack = new Stack<>();int result = 1;if (n < 0) return 0;if (n == 0) return 1;else {while (n != 0) {Node node = new Node();node.a = n;node.b = n / 2;n = node.b;stack.push(node);}while (!stack.isEmpty()) {result = result * stack.pop().a;}}return result;}/*** (推荐解法)非递归方法2:利用栈,单参数*/public static int non_recursion2(int n) {Stack<Integer> stack = new Stack<>();int result = 1;if (n < 0) return 0;if (n == 0) return 1;else {while (n != 0) {stack.push(n);n = n / 2;}while (!stack.isEmpty()) {result = result * stack.pop();}}return result;}/*** 非递归方法3:自定义数组模拟栈,双参数*/public static int non_recursion3(int n) {class Node {int a;int b;}Node[] node = new Node[100];int result = 1;int top = 0;if (n < 0) return 0;if (n == 0) result = 1;else {while (n != 0) {top++;node[top] = new Node();node[top].a = n;node[top].b = n / 2;n = node[top].b;}while (top != 0) {result = result * node[top--].a;}}return result;}/*** 由于是尾递归,因此可以不用栈*/public static int non_recursion4(int n) {int result = 1;if (n < 0) return 0;if (n == 0) return 1;else {while (n != 0) {result = result * n;n = n / 2;}return result;}}
}

数据结构:利用栈,将递归转换为非递归的方法相关推荐

  1. 利用栈将递归转换为非递归的方法

    通过上述讨论,可以看出递归程序在执行时需要系统提供隐式栈这种数据结构来实现,对于 一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化可直接写出相应的非递归算法. 这种利用栈消除递归过程的步骤如 ...

  2. 如何用堆栈和循环结构代替递归调用--递归转换为非递归的10条军规

    10 Rules (steps) for replacing the recursive function with stack and while-loop 转自http://www.codepro ...

  3. 将递归函数转换为非递归形式

    转自 :https://blog.csdn.net/sunny_ss12/article/details/47095381 1. 递归的调用原理:分而治之 为求一个大规模问题的问题,可以: (1)将原 ...

  4. 利用栈实现递归函数的非递归计算(非递归求阶乘)

    递归程序在执行时需要系统提供隐式栈这种数据结构来头现,对于一般的递归过程,仿照递归算法执行过程中递归工作栈的状态变化可直接写出相应的非递归算法,利用栈消除递归过程的步骤如下. (1)设置一个工作栈存放 ...

  5. python创建树结构、求深度_数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)...

    前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...

  6. 二叉树的先中后序递归和非递归遍历(数据结构作业)

    一.设计思想 我创建二叉树是用的先序创建,其中用'#'代表空节点. 1.递归先序遍历 (1)如果当前节点为空节点(用'#'代表空节点),结束当前函数 (2)打印当前节点 (2)递归当前节点的左子树 ( ...

  7. 【Java数据结构】二叉树的前中后序遍历(递归和非递归)

    二叉树的遍历 递归做法 前序遍历 中序遍历 后序遍历 非递归 前序遍历 中序遍历 后序遍历 二叉树遍历是二叉树的一种重要操作 必须要掌握 二叉树的遍历可以用递归和非递归两种做法来实现 递归做法 前序遍 ...

  8. 汉诺塔的改编题(用栈求解,分别递归和非递归)

    限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间,求当塔有N层的时候,打印最优移动过程和最优移动总步数 例如:当塔为两层时,最上层的塔记为1,最下层的塔记为2,则 ...

  9. 【恋上数据结构】递归(函数调用过程、斐波那契数列、上楼梯、汉诺塔、递归转非递归、尾调用)

    递归(Recursion) 什么是递归? 函数的调用过程(栈空间) 函数的递归调用过程 递归实例分析(1 + 2 + 3 + ... + 100 的和) 递归的基本思想.使用套路 斐波那契数列 fib ...

最新文章

  1. 10 个 Python 工程师,9 个不合格!!
  2. Groovy - 基本特性
  3. python编程有用吗-分享8点超级有用的Python编程建议
  4. jQuery学习笔记之extend方法小结
  5. 在你的Fckeditor安装Google map plugin
  6. Nginx 反向代理、动静分离、负载均衡及配置实例
  7. 顶级技术大咖,揭秘实时音视频开发的超级风口
  8. java解决导出word用wps打开正常,用office打开是html的标签的问题
  9. 2--OC -- 类的创建与实例化
  10. qml 不刷新 放大还原_【显示器选择详解】你的电脑能否带动高分辨率,高刷新率显示器?...
  11. 只需修改一个像素,让神经网络连猫都认不出 | 论文+代码
  12. android mm 修改路径,Android 编译系统模块
  13. JavaWeb项目开发案例精粹-第6章报价管理系统-001需求分析及设计
  14. 终日奔波只为饥,方才一饱便思衣
  15. 几类常用Case工具介绍(有点老,但还是具有参考性,对应找较新版本就是了)...
  16. 如何找到想要的资源?
  17. 苹果安卓APP下载地址合并为一个二维码
  18. 鲁大师发布2021年Q1季度报告,哪些手机最强?
  19. 如何在linux内核中增加对应的Makefile和Kconfig选项?
  20. 读《读大学,究竟读什么》感悟一

热门文章

  1. CodeForces - 617E XOR and Favorite Number(莫队)
  2. 中石油训练赛 - 腿部挂件(可持久化字典树)
  3. HDU - 1527 取石子游戏(威佐夫博弈)
  4. UVA - 11882Biggest Number dfs+期望剪枝
  5. 算法模板-广度优先遍历
  6. java jfreechar鱼刺图_java使用jfreechar绘制饼型统计图
  7. Java笔记——Java代码块的执行顺序
  8. C++虚继承(八) --- 虚继承与继承的差异
  9. 手把手教你玩转ARP包(二)
  10. 大侠稍等!URL 中为何出现奇怪的字符