(转)递归转非递归的思路和例子

转自:http://blog.51cto.com/cnn237111/1241956

某些算法逻辑,用递归很好表述,程序也很好写。理论上所有的递归都是可以转换成非递归的。如果有些场合要求不得使用递归,那就只好改成非递归了。

通常改成非递归算法的思路,就是使用临时的一个栈来存放计算的临时值。

下面演示2个例子。

示例一:

假设有如下的递归函数

f(1)=3

f(2)=11

f(n)=4*f(n-1)-f(n-2)

那么写成代码,这个递归函数就是如下:

1
2
3
4
5
6
7
8
9
static int f(int x)
        {
            if (x == 1)
                return 3;
            else if (x == 2)
                return 11;
            else
                return 4 * f(x - 1) - f(x - 2);
        }

如果改写成非递归,那么肯定是要用到循环。

由于计算第n个值的时候,要用到第n-1和第n-2个值,因此,至少要把这2个值存起来。然后使用的时候这2个值都出栈,计算出第n个值,然后,再把第n-1个值和第n个值入栈,以方便计算第n+1的值。具体代码如下:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static int f_1(int x)
        {
            Stack<int> s = new Stack<int>();
            for (int i = 1; i <= x; i++)
            {
                if (i == 1)
                    s.Push(3);
                else if (i == 2)
                    s.Push(11);
                else
                {
                    int tmp1 = s.Pop();//栈中至少有2个元素了,出栈后以计算下一个元素
                    int tmp2 = s.Pop();
                    int tmp = 4 * tmp1 - tmp2;
                    s.Push(tmp1);
                    s.Push(tmp);//计算结果入栈
                }
            }
            return s.Pop();//返回栈顶元素
        }

示例二:遍历二叉树

二叉树的先序遍历,中序遍历,后序遍历,通常是递归实现的,因为很好理解。此处不再赘述递归版本。

假设有一个二叉树:

image_thumb

先用代码构造出这棵树。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#region 节点的定义
class node
{
    public string nodevalue;
    public node leftchild, rightchild;
    public node()
    { }
    public node(string value)
    {
        nodevalue = value;
    }
    public void assignchild(node left, node right)//设定左右孩子
    {
        this.leftchild = left;
        this.rightchild = right;
    }
    public bool hasleftchild//是否有左孩子
    {
        get
        {
            return (leftchild != null);
        }
    }
    public bool hasrightchild//是否有右孩子
    {
        get
        {
            return (rightchild != null);
        }
    }
    public override string ToString()
    {
        return nodevalue;
    }
}
#endregion

***************************

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void Main(string[] args)
      {
          node node_a = new node("a");
          node node_b = new node("b");
          node node_c = new node("c");
          node node_d = new node("d");
          node node_e = new node("e");
          node node_f = new node("f");
          node node_g = new node("g");
          node node_h = new node("h");
          node node_i = new node("i");
          //构造一棵二叉树
          node_a.assignchild(node_b, node_c);
          node_b.assignchild(node_d, node_e);
          node_c.assignchild(node_f, node_g);
          node_e.assignchild(node_h, node_i);
  }

****************************************

非递归版本实现先序遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//先序遍历
 static void preorder_visit_1(node root)
        {
            Stack<node> s = new Stack<node>();
            s.Push(root);//先序遍历。首先访问的是根结点,把根节点放入栈中
            while (s.Count > 0)
            {
                node r = s.Pop();//当前要访问的结点出栈。
                Console.Write(r.nodevalue);
                //先序遍历的顺序是根,左,右。
                //由于栈的先入后出的特性,因此先插入右孩子,后插入左孩子,能保证取出来的时候是先左后右
                if (r.hasrightchild) //如果有右孩子,则右孩子入栈
                {
                    s.Push(r.rightchild);
                }
                if (r.hasleftchild)//如果有左孩子,则左孩子入栈
                {
                    s.Push(r.leftchild);
                }
            }
        }
//中序遍历
 static void inorder_visit_1(node root)
        {
            Stack<node> s = new Stack<node>();
            s.Push(root);
            while (s.Count > 0)
            {
                while (s.Peek() != null && s.Peek().hasleftchild)//把该节点的左子树全部遍历。
                    //如果s.Peek()==null,说明栈中null下的元素的左孩子已经遍历过了,该访问null下的元素本身了。
                {
                    s.Push(s.Peek().leftchild);
                }
                if (s.Peek() == null)
                    s.Pop();
                if (s.Count > 0)
                {
                    var node = s.Pop();
                    Console.Write(node.nodevalue);
                    s.Push(node.rightchild);//如果没有右子树,放入空结点
                }
            }
        }

转载于:https://www.cnblogs.com/heluan/p/8551615.html

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

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

相关文章

iOS - 富文本

iOS--NSAttributedString超全属性详解及应用&#xff08;富文本、图文混排&#xff09; ios项目中经常需要显示一些带有特殊样式的文本&#xff0c;比如说带有下划线、删除线、斜体、空心字体、背景色、阴影以及图文混排&#xff08;一种文字中夹杂图片的显示效果&#xff09;。…

pdf.js 文字丢失问题 .cmaps

使用pdf.js 展示pdf文件 需求&#xff1a;电子发票类的pdf文件&#xff0c;以base64流的形式请求到&#xff0c;在浏览器中展示pdf文件 遇到的问题&#xff1a; 正常展示后&#xff0c;部分文字无法正常显示&#xff0c; 正常显示如下&#xff1a; 文件目录&#xff1a; js:fun…

超过4g的文件怎么上传到linux,怎么免费上传大于4G的文件到百度云 大于4G的文件不开会员怎么上传到百度云...

4G管家appv1.0 安卓版类型&#xff1a;系统工具大小&#xff1a;13.1M语言&#xff1a;中文 评分&#xff1a;10.0标签&#xff1a;立即下载百度云可以非常方便大家存储一些大文件资料&#xff0c;而且百度云的容量也非常高&#xff0c;不过如果你是普通用户的话要想上传大于4g…

android 屏幕坐标色彩,Android自定义View实现颜色选取器

Android 自定义View 颜色选取器&#xff0c;可以实现水平、竖直选择颜色类似 SeekBar 的方式通过滑动选择颜色。效果图xml 属性1.indicatorColor 指示点颜色2.indicatorEnable 是否使用指示点3.orientation 方向horizontal 水平vertical 竖直使用复制 \library\src…\ColorPick…

linux右键菜单的截图,Linux: 给右键菜单加一个“转换图片为jpg格式”

Linux上通常都会安装imagemagick这个小巧但又异常强大的工具。这个软件提供了一系列很好用的功能。这里说一说如何使用它的convert命令转换图片为jpg格式&#xff0c;以及如何把它添加到Thunar的右键菜单。convert转换图片为jpg格式用起来超简单&#xff1a;convert -format jp…

eclipse实现Android登录功能,eclipse开发安卓登录

划线的地方怎么解决啊&#xff1f;有没有大佬知道如何修改package com.example.login;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.content.SharedPreferences.Edito…

android tcp 最优窗口,Android 面试必备 - 计算机网络基本知识(TCP,UDP,Http,https)...

简介HTTP协议(超文本传输协议)和 UDP(用户数据包协议)&#xff0c;TCP 协议(传输控制协议)TCP/IP是个协议组&#xff0c;可分为四个层次&#xff1a;网络接口层、网络层、传输层和应用层。在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。在传输层中有TCP协议与UDP…

c语言10个数如何求最大值,C语言,输入10个数怎样输出10个数中最大值,最小值(大一计算机)...

可以参考下面的代码&#xff1a;#include int main(){int loop 10;int min, max, value;do{printf("输入整数:");scanf("%d", &value);if (loop10) {max min value; loop--; continue;} else {if (value > max) max value;if (value loop--;}} …

android波纹效果弹窗,Android自定义View实现波纹效果

Android自定义View实现波纹效果时间&#xff1a;2017-05-27 来源&#xff1a;移动互联网学院1、引言&#xff1a;随着Android智能手机的普及&#xff0c;Android应用得到了大力支持&#xff0c;而Android应用的市场前景也是非常的强势。在Android应用的实际开发中&#xff…

图像滤镜艺术---Oilpaint油画滤镜

图像滤镜艺术---Oilpaint油画滤镜 原文:图像滤镜艺术---Oilpaint油画滤镜Oilpaint油画滤镜 图像油画效果实际上是将图像边缘产生一种朦胧&#xff0c;雾化的效果&#xff0c;同时&#xff0c;将一定的边缘模糊化&#xff0c;这样图像整体上看去像素与像素之间就像雾一样随机呈现…

转:数据库收缩

1. 数据库的相关属性 在MS中创建数据库时会为数据库分配初始的大小&#xff08;如下图&#xff1a;数据库和日志两个文件&#xff09;&#xff0c;随着数据库的使用文件会逐渐增大。数据库文件大小的增加有两种方式&#xff1a; 自动增长&#xff1a;在自动增长中可以设置每次的…

懒加载与预加载

前端性能优化中图片资源的优化。 1.懒加载&#xff08;延迟加载&#xff09; 1.图片进入可视区域之后请求图片资源&#xff1b; 2.对于电商等图片较多&#xff0c;页面很长的业务场景很适用&#xff1b; 3.可以减少无效资源的加载&#xff1b; 4.并发加载的资源过多会阻塞js的加…

8.使用Exists监控ZNode的三大Change事件

一、 zookeeper是一个分布式的协调程序&#xff08;所有程序都是通过订阅它来相互感知&#xff09;1. tcp&#xff08;长链接&#xff09; watcherserver -》clientclient -》server2. Driver 中的方法 exists() 监控一个znode的 CURD 的操作。client1 client2 同时订阅 baidu…

[SDOI2016]储能表

Description 有一个 n 行 m 列的表格&#xff0c;行从 0 到 n−1 编号&#xff0c;列从 0 到 m−1 编号。每个格子都储存着能量。最初&#xff0c;第 i 行第 j 列的格子储存着 (i xor j) 点能量。所以&#xff0c;整个表格储存的总能量是&#xff0c; 随着时间的推移&#xff0…

html对图片轮播脚本怎么调用,【jquery前端开发】可调整的幻灯片(图片轮播)

第一次写博客&#xff0c;希望接下来写的东西 或多或少能帮到些人&#xff0c;虽然这些东西都是一些大神前辈们写了无数遍的东西&#xff0c;但我尽量以一名小白的视角把代码写得清楚点&#xff0c;好心人的就给点赞吧。1.前期准备这是我们编写代码前必须要做的事&#xff0c;在…

计算机主机信息怎么看,本机电脑硬件配置信息怎么看?Win7/Win10查看详细电脑配置方法...

电脑配置决定了一台电脑的性能好坏&#xff0c;如果电脑配置没有达到游戏或者软件的要求&#xff0c;那么肯定无法流畅运行的。对于一些小白用户不知道如何查看电脑硬件配置&#xff0c;那么本机电脑硬件配置信息怎么看&#xff1f;下面装机之家小编分享一下Win7/Win10查看详细…

《Java技术》第一次作业

&#xff08;一&#xff09;、学习总结 1.在java中通过Scanner类完成控制台的输入&#xff0c;查阅JDK帮助文档&#xff0c;Scanner类实现基本数据输入的方法是什么&#xff1f;不能只用文字描述&#xff0c;一定要写代码&#xff0c;通过具体实例加以说明。 文本扫描类Scanner…

计算机主机开机为什么显示器不开,电脑开机后显示器不亮怎么办?电脑开机后显示器没反应的解决办法...

电脑开机后显示器不亮怎么办&#xff1f;电脑开机故障屡见不鲜&#xff0c;最近又有用户反馈开机问题了&#xff0c;一用户反馈说&#xff0c;电脑主机是可以正常开机的&#xff0c;但就是显示器不亮&#xff0c;这是怎么回事呢&#xff1f;出现这种情况可能是显示器或主机故障…

斯坦福-随机图模型-week4.0_

title: 斯坦福-随机图模型-week4.0 tags: note notebook: 6- 英文课程-9-Probabilistic Graphical Models 1: Representation --- 斯坦福-随机图模型-week4.0 最大期望收入模型 简答的决策 我们使用随机图模型进行决策需要的原料是什么ne ? 我们需要决策的情景一些列的可能的行…

计算机行业哪个会议论文最好,《第三次全国电子计算机专业学术会议论文选集》...

1964年12月&#xff0c;国防工业出版社出版了《第三次全国电子计算机专业学术会议论文选集》(以下简称《选集》)&#xff0c;由中国电子学会计算机专业委员会编辑&#xff0c;《选集》内容覆盖之广令人震惊。《选集》的内容表达了1961年以来国内计算技术在理论与实际方面的工作…