图形辅助,理解递归

对大多数程序员来说,递归算法都不算陌生。甚至很多时候,使用递归算法解决一些简单问题是基础教材的起步课程。但是,当递归算法遇到稍微复杂的数据结构,如二叉搜索树的时候。别说让你直接写出算法,就是把标准答案摆在你的面前让你理解,我们恐怕都会抓耳挠腮。如果你也有类似的困扰请不要灰心,因为包括我在内几乎我遇到的每一个码农在这些方面都显得一筹莫展。究其原因,我认为这其实是认知心理的一种表现——我们无法胜任同时正向思考与反向记忆——大多数的时候,我们可以轻松应付函数的一层层递进,却很难记住每一层的返回值。终于我发现通过一种简单而有效的图形结构可以让我们理解各类递归算法,下面进入正题。

定义在一个标准的二叉搜索树算法中包含一个方法以获取小于某一个键值Key的最大节点对象:

/**
 * Node包含一个键值对<Key extends Comparable<Key>, Value>
 * 以及一棵左子树和一棵右子树Node left, right
 *
 * class Node {
 *     private Key key;
 *    private Value val;
 *    private Node left, right;
 * }
 */
Node floor(Node n, Key key) {
    if (n == null) {
        return null;
    }
    int cmp = key.compareTo(n.key);
    if (cmp == 0) {
        return n;
    } else if (cmp < 0) {
        return floor(n.left, key);
    } else {
        Node r = floor(n.right, key);
        if (r != null) {
            return r;
        } else {
            return n;
        }
    }
}

算法不复杂,对二叉搜索树不太了解的可以先去熟悉一下数据结构。可是想读懂这几行代码确实令我头疼,毕竟如果读不懂就不可能记住更不可能在需要的时候自己写出来。接下来就是见证奇迹的时刻:

首先,任何一种递归算法都必然包含四种要素:输入,输出,递归条件和终止条件。floor方法含有两个递归条件cmp<0和cmp>0以及三个终止条件n==null, cmp==0和r==null。

其次,我们将要通过简单的图形来代表层层的递归顺序,并且帮助我们在达到终止条件的时候记录返回值。如果在稿纸上绘制甚至还可以更简洁一些。

以下是一个完整的演示: Node(H) floor( Node(S), Key(J) )

跟着floor方法绘制递归图你大概应该获得和我类似的结果:

是不是感觉瞬间思路清晰了!如果你也觉得这样的方法对你有所帮助或者还有更好的建议不妨在留言中分享出来。

原文地址:https://www.cnblogs.com/learnhow/p/10989532.html

时间: 2024-10-11 20:03:55

图形辅助,理解递归的相关文章

java数据结构与算法之递归思维(让我们更通俗地理解递归)

[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53452971 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设计与实现 j

如何真正的理解递归?

/* * 理解递归的真正含义:当运行到调运自身时先停止执行后边的代码 重新调用自身当所有调用自身的代码运 * 行完成后再重新按栈的形式重新由后向前一次调用自身之后的代码 * 特点:递归调用很容易导致占用大量的空间,递归的效率不高 * * 下列代码中通过输出n的值理解递归调用其实就是堆栈的运用使用递归很容易造成堆栈溢出 * */ package arithmetic; public class recursion { public static void main(String[] args) {

傻瓜式理解递归之php递归

写程序这么久了,有时候别人会问道一些算法比如排序啊,递归啊,总是不知道该怎么去说,今天就来整理一下,让更多的人去傻瓜式的理解递归.递归在网络上有很多定义,但有这么一句话听的最多:递归就是自己调用自己!引用百科的一个故事去理解: 从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?"从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?'从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?--'" 这样的故事是不是在做

python之理解——递归

古之欲明明德于天下者,先治其国:欲治其国者,先齐其家:欲齐其家者,先修其身:欲修其身者,先正其心:欲正其心者,先诚其意:欲诚其意者,先致其知,致知在格物.物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平. 这是从林海峰博客里面copy的.很好的解释了,python函数的递归. 那什么是递归? 在函数内部,可以调用其他函数.如果在调用一个函数的过程中直接或间接调用自身本身 def digui(n): print(n) digui(n) digui(

使用Python语言理解递归

递归 一个函数在执行过程中一次或多次调用其本身便是递归,就像是俄罗斯套娃一样,一个娃娃里包含另一个娃娃. 递归其实是程序设计语言学习过程中很快就会接触到的东西,但有关递归的理解可能还会有一些遗漏,下面对此方面进行更加深入的理解 递归的分类 这里根据递归调用的数量分为线性递归.二路递归与多重递归 线性递归 如果一个递归调用最多开始一个其他递归调用,我们称之为线性递归. 例如: def binary_search(data, target, low, high): """ 二分查

初学者如何理解递归

0 递归的定义 如果你没明白递归的定义,参见本文"0.递归的定义" 1 从斐波那契数列开始 斐波那契的递推公式 斐波那契数列递归算法和递推公式类似 int fibo(int x) { if (x<3) return 1; return fibo(x-1)+fibo(x-2); } 就这么简单?没错,通过这个例子可以看出,递归函数只需要写两部分,一个是递归终止条件(if(x<3) return 1;),一个是递归的“交接”(return fibo(x-1)+fibo(x-2)

Java学习之理解递归

Java支持递归.递归是根据自身定义内容的过程.就Java编程而言,递归是一个允许方法调用自身的特性.调用自身的方法被称为递归.典型的例子就是阶乘的计算,N的阶乘就是从1到N之间所有整数的乘积. 当方法调用自身时,在堆栈上为新的局部变量和参数分配内存,并使用这些新的变量从头开始执行方法的代码.当每次递归调用返回时,将旧的局部变量和参数从堆栈中移除,并将执行控制恢复到方法内部的调用点.递归方法被称为"望远镜式"的方法,可以自由伸缩. 许多例程的递归版本,它们的执行速度比与之等价的迭代版本

一个强悍的极简单递归小例子帮你从程序执行的角度理解递归

1 public class test { 2 public static void main(String[] args) { 3 swap(3); 4 } 5 public static int i=1; //全局变量 6 public static void swap(int a){ //局部变量 7 if(a>0){ 8 a--; 9 System.out.println("第"+i+"层:"); 10 System.out.println("

十张gif动态图让你理解递归等算法概念

上图是while循环 上图是带if/else的while循环 上图是递归概念演示 上图是递归代码演示 上图是递归求斐波那契 上图是递归求阶乘 上图是按值传递和按引用传递的区别 上图是二分检索树 上图是线性检索和二分检索求 1 的位置 上图是线性检索和二分检索求 23 的位置