首页 > 其他分享 >二叉树的递归套路

二叉树的递归套路

时间:2024-08-08 12:17:12浏览次数:12  
标签:Info 递归 套路 findB 信息 二叉树 ans 节点 left

二叉树的递归套路

二叉树结构

二叉树是一个将数据组织成头尾相连的特殊链表,每一个数据单元与链表一样有一个指向其的指针,但与链表不同的是其可以有两个指向其他单元的指针,分别是其左孩子与右孩子。采用该这种结构,最终数据的呈现形式会与“链”不一样,而呈现出了一种树的结构。

对于这种树型结构,每一棵完整的子树都有头节点、左孩子与右孩子。头节点可以从左右孩子分别收集信息并向上传递,给自己的头节点。这就是二叉树递归套路的基本准则,采用这种方式去写递归算法,就可以简单地遍历所有的二叉树节点并收集信息,在整个二叉树地头节点进行汇集。

二叉树的递归套路步骤

以最低祖先点阐述递归套路的具体执行。最低祖先点:给定一颗二叉树中的两个节点,求二者向根节点溯源路径中第一个相同的节点。

步骤1:构建信息类Info

对于一个我们想要解决的实际问题,当前的处理思想是子节点一直向上提交信息,那么这个信息一定就要能推断问题或者解决问题。所以第一个步骤为:假设头节点可以获取左右孩子的所有信息,构建需要解决这个问题的方法类

问题分析:想要找到二者的最先祖先点,则该点下路径搜索中必须要能找到这两个节点,而由于是最低的公共祖先节点,所以要返回第一个可以在孩子中搜索到二者的节点,那么信息中一定要包含这个返回节点以及是否能找到两个节点的信息,因此有如下定义:

public static class Info {
    public boolean findA;//是否这条路径有节点A
    public boolean findB;//是否这条路径有节点B
    public Node ans;//最找在此节点下路径发现节点A,B的节点
    public Info(boolean fA, boolean fB, Node an) {
        findA = fA;
        findB = fB;
        ans = an;
    }
}

步骤2:构建自身的信息体

确定好信息类后,我们的递归函数的返回类型就是信息类,因为我们想要左右孩子直接向头节点返回信息类,然后头节点处理这些信息,并结合自己的信息,生成自己的信息体。因此第二个步骤为:头节点从左右孩子获取左右信息体,结合自身信息处理得到本节点的信息体。

Info leftInfo = process(x.left, a, b);
Info rightInfo = process(x.right, a, b);
boolean findA = (x == a) || leftInfo.findA || rightInfo.findA;//此节点的findA为:左孩子下可以找到||右孩子下可以找到A||自己就是A
boolean findB = (x == b) || leftInfo.findB || rightInfo.findB;//此节点的findB为:左孩子下可以找到||右孩子下可以找到B||自己就是B
Node ans = null;
if (leftInfo.ans != null) {
    ans = leftInfo.ans;
} else if (rightInfo.ans != null) {
    ans = rightInfo.ans;
} //如果左右孩子中的返回信息中已经设置好了答案节点那么就直接设置为本信息体的答案,否则就在本节点进行一次信息处理,看看本节点是否有答案。
else {
    if (findA && findB) {
        ans = x;
    }
return new Info(findA, findB, ans);//返回本节点的信息体

必须注意本节点收到左右孩子的信息,结合自身信息进行加工处理时必须要考虑所有的情况。

步骤3:边界条件的处理

这是对头节点下探到自己孩子,返回为空的处理,程序的入口是头节点,会一直下探,探到底部的节点,底部的节点此时也会调用:

Info leftInfo = process(x.left, a, b);
Info rightInfo = process(x.right, a, b);

并得到底部节点的空的孩子的返回信息,这时要合理设置底部的返回信息避免其会对后续的信息处理产生干扰,在本例中,信息体以是否找到节点的boolean类型为核心,所以,为了不干扰结果,当本节点为空时,应该立刻返回一个不干扰的信息体:

return new Info(false,false,null);

代码汇总

经历所有的步骤就有了总的代码:

//1.信息体的设置
public static class Info {
    public boolean findA;
    public boolean findB;
    public Node ans;

    public Info(boolean fA, boolean fB, Node an) {
        findA = fA;
        findB = fB;
        ans = an;
    }
}
//递归函数,返回类型是信息体类
public static Info process(Node x, Node a, Node b) {
    //边缘的返回
    if (x == null) {
        return new Info(false, false, null);
    }
    //得到左右孩子的信息,并结合自身信息,加工出自己的信息体,并向上返回。
    Info leftInfo = process(x.left, a, b);
    Info rightInfo = process(x.right, a, b);
    boolean findA = (x == a) || leftInfo.findA || rightInfo.findA;
    boolean findB = (x == b) || leftInfo.findB || rightInfo.findB;
    Node ans = null;
    if (leftInfo.ans != null) {
        ans = leftInfo.ans;
    } else if (rightInfo.ans != null) {
        ans = rightInfo.ans;
    } else {
        if (findA && findB) {
            ans = x;
        }
    }
    return new Info(findA, findB, ans);
}

对于递归套路的理解

整个递归函数的关键是假设头节点可以从左右孩子获得所有想要的信息,这一步是通过:

Info leftInfo = process(x.left, a, b);
Info rightInfo = process(x.right, a, b);

来实现的,那么在实际的程序运转中,会怎样去进行这个递归方法呢,首先我们知道JAVA实现递归函数是依靠方法栈,Java运行一个程序时,会首先向栈中压入其main函数,然后每当main函数中调用了其他函数则继续在栈中压入其他函数,其他函数产生了调用亦然。对于本方法亦然,所以执行到本方法时,会将该方法以栈帧的形式压入方法栈中。

以程序执行到本函数为起点:

栈中压入本方法f(root),开始执行本程序中传入了二叉树的根节点,首先会经过一个空指针判断,如果为空则直接返回,不为空,则会向本程序中传入根节点的左孩子;再次执行以root.left为当前节点的程序,栈中压入本方法f(root.left),再次经历一个空指针判断,然后继续向本程序中传入当前节点的左孩子;再次执行以root.left.left为当前节点的策划功能,栈中压入方法f(root.left.left)……

这个过程会一直重复,直到f(root.left........leftn)进入程序后在判断环节发现其是空,那么就会直接返回,这样该方法结束,方法栈中弹出该方法,执行f(root.left...leftn-1)方法,此时, Info leftInfo = process(x.left, a, b);已经有了返回值,为new Info(false, false, null),该程序就会进入下一条代码的执行:Info rightInfo = process(x.right, a, b);,由于其也为空,则也会返回new Info(false, false, null),这样底部节点就收到了左右信息,就可以开始处理自身信息并加工自己的信息体返回。

那么当底部节点完成其信息体后,这个节点其实也是其他节点的左节点,它的返回信息会被上层代码接收即f(root.left...leftn-2)中的Info leftInfo = process(x.left, a, b);这样,f(root.left...leftn-2)就可以去执行下一行,去接收其右节点信息,这个过程与刚刚的左节点信息上交也是类似的。

总的来说,程序会按照一个递归序的顺序去遍历所有的节点,然后逐级上交信息, 最终在根节点汇总信息后,返回整棵树的信息。

  1. f(1)压入栈中,收集左信息,f(2)压入栈中

  2. f(2)收集左信息,f(3)压入栈中

  3. f(3)将f(3.left)压入栈中,直接返回,将f(3.right)压入栈中,也直接返回,f(3)处理完自身信息,程序结束,方法栈中弹出f(2)。

  4. 执行f(2)的收集右信息,将f(4)压入栈中

  5. f(4)会执行一个跟步骤三一样的过程。并返回作为f(2)的右信息。

  6. f(2)已经搜集到了左右信息,处理完信息后,返回信息给f(1)中的收集左信息环节,进入f(1)的收集右信息环节。

  7. 首先以f(5)为f(1)右信息的返回,压入f(5)。f(5)以f(6)为其左信息。f(6)执行结束,压入f(7)作为f(5)右信息的返回,f(7执行结束,处理f(5)信息,f(1)中得到右信息,最终返回f(1)信息,得到整棵树的信息。

标签:Info,递归,套路,findB,信息,二叉树,ans,节点,left
From: https://www.cnblogs.com/typingwithtoes/p/18348683

相关文章

  • Java数据结构 | 二叉树基础及基本操作
    二叉树一、树型结构1.1树的概念1.2关于树的一些常用概念(很重要!!!)1.3树的表示形式1.4树的应用二、二叉树2.1二叉树的概念2.2两种特殊的二叉树2.3二叉树的性质2.4二叉树的存储2.5二叉树的基本操作2.5.1代码说明2.5.2二叉树的遍历2.5.3二叉树的基本操作1、获取树......
  • 趣味Python游戏编程:第3章 递归函数的威力:扫雷
    趣味Python游戏编程:第3章递归函数的威力:扫雷在第2章中,我们制作了一个拼图游戏,玩家通过鼠标操作图片块移动。本章设计一款扫雷游戏,玩法是在一个方块阵列中随机埋设一定数量的地雷,然后由玩家逐个打开方块,并以排除所有地雷为最终游戏目标。如果玩家打开的方块中有地雷,则游戏......
  • 是你的java二叉树啊啊啊
    1.二叉树的最大深度问题:计算二叉树的最大深度(或高度)。Java实现:publicclassTreeNode{intval;TreeNodeleft;TreeNoderight;TreeNode(intx){val=x;}}publicclassSolution{publicintmaxDepth(TreeNoderoot){if(root==......
  • 程序设计部分 函数的递归 第4关:使用递归进行自动分析
    任务描述本关任务:计算逆波兰表达式的值。相关知识放苹果问题把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?注意:5,1,1和1,5,1是同一种分法。我们可以先假设有一个函数count(m,n)能告诉我们m个苹果放n个盘子有多少种放法,然后在此基础上进行......
  • 《重生到现代之从零开始的C语言生活》——函数递归
    递归啥是递归啊递归是解决问的一种方式,简单来说,就是函数自己调用自己递归解决问题把复杂的大问题转化为一个一个与原文题相似的小问题。递归的思想就是把大事化小在递归中,递就是递推,归就是回归递归中的限制条件递归必须存在限制条件,当满足这个条件时,递归不在继续每次......
  • 超详细明了的C语言函数递归,望周知。(包含求n的阶乘顺序打印⼀个整数的每⼀位求第n个斐
    1.递归是什么?递归是学习C语⾔函数绕不开的⼀个话题,那什么是递归呢?递归其实是⼀种解决问题的⽅法,在C语⾔中,递归就是函数⾃⼰调⽤⾃⼰。写⼀个史上最简单的C语⾔递归代码#include<stdio.h>intmain(){printf......
  • 【平衡二叉树】数据结构—平衡二叉树
    平衡二叉树(BalancedBinaryTree)是一种特殊的二叉树,它的左右子树的高度差不超过1,这样可以保证树的高度相对较低,从而使得查找、插入和删除操作的时间复杂度保持在。平衡二叉树的基本概念1.二叉树:每个节点最多有两个子节点,分别称为左子节点和右子节点。2.平衡条件:对于每个......
  • 二叉树刷题,bfs刷题
    有些题目,你按照拍脑袋的方式去做,可能发现需要在递归代码中调用其他递归函数计算字数的信息。一般来说,出现这种情况时你可以考虑用后序遍历的思维方式来优化算法,利用后序遍历传递子树的信息,避免过高的时间复杂度。遍历,对每一个结点进行操作,可以是找这个结点的旁边结点也可以......
  • 二叉树递归解决问题刷题 (一)
    遇到和深度相关的题目,可以用dfs递归遍历深度获取bfs结果来做513.找树左下角的值如何找二叉树最底层最左边节点的值呢,就是dfs遍历深度,来获取,最后一层的第一个元素就是。classSolution:def__init__(self):#记录二叉树的最大深度self.maxDepth=......
  • NC 实现二叉树先序,中序和后序遍历
    系列文章目录文章目录系列文章目录前言前言前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。描述给定一棵二叉树,分别按照二叉树先序,中序和后序打印所有的节点。i......