Java数据结构第十三期:走进二叉树的奇妙世界(二)

news/2025/2/25 18:26:36

专栏:数据结构(Java版)

个人主页:手握风云

目录

一、二叉树的遍历

1.1. 前序遍历

1.2. 中序遍历

1.3. 后序遍历

1.4. 完整代码

二、二叉树的基本操作

2.1. 获取树中结点个数

2.1. 获取叶子结点个数

2.3. 获取第k层结点的个数

2.4. 获取二叉树的高度

2.5. 检测值为value的元素是否存在


一、二叉树的遍历

1.1. 前序遍历

        前序遍历又叫先根遍历。每一个节点的遍历顺序都是按照“根——>左子树——>右子树”的顺序来遍历,每遇到一个新的结点都看作是一棵新的树。如果遇到空,则递归回上一个节点。A的右子树遍历过程也如下,所以前序遍历的结果为“ABDCEF”。

1.2. 中序遍历

       中序遍历的顺序为“左子树——>根——>右子树”,遇到一个结点,先去遍历左子树,如果该节点的根为空,才能递归回来进行打印。所以中序遍历的结果为“DBAECF”。

1.3. 后序遍历

        后序遍历的顺序为“左子树——>右子树——>根”,遍历过程与上面两种都差不多,这里不再多说。后序遍历的顺序为“DBEFCA”。

1.4. 完整代码

public class BinaryTree {
    static class TreeNode{
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }

    public TreeNode CreateTree(){
        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');

        A.left = B;
        A.right = C;
        B.left = D;
        C.left = E;
        C.right = F;

        return A;
    }

    public void PrevOrder(TreeNode root){//前序遍历
       if(root == null){
           return;
       }
       System.out.print(root.val+" ");
       PrevOrder(root.left);
       PrevOrder(root.right);
    }

    public void InOrder(TreeNode root){//中序遍历
        if(root == null){
            return;
        }
        InOrder(root.left);
        System.out.print(root.val+" ");
        InOrder(root.right);
    }

    public void PostOrder(TreeNode root){//后序遍历
        if(root == null){
            return;
        }
        PostOrder(root.left);
        PostOrder(root.right);
        System.out.print(root.val+" ");
    }
}
public class Test {
    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        BinaryTree.TreeNode root = binaryTree.CreateTree();
        System.out.print("前序遍历:");
        binaryTree.PrevOrder(root);
        System.out.println();
        System.out.print("中序遍历:");
        binaryTree.InOrder(root);
        System.out.println();
        System.out.print("后序遍历:");
        binaryTree.PostOrder(root);
    }
}

二、二叉树的基本操作

2.1. 获取树中结点个数

     我们先回想以下如何获取链表中的结点个数。我们定义一个ListNode cur变量,当cur不为空时,count递增。同样的,我们上面已经实现了二叉树结点的遍历,我们也只需要再定义一个计数器,只要root不为空,countNode就递增。

    public void NodeSize(TreeNode root){
        if(root == null){
            return;
        }
        CountSize++;
        NodeSize(root.left);
        NodeSize(root.right);
    }

       上面的是遍历思路,还有一种子问题思路。整棵树的结点个数等于左树的结点数和右树的结点数再加一,只要root为空,那么我们就可以结束递归。

    public int NodeSize2(TreeNode root){
        if(root == null){
            return 0;
        }
        int tmp = NodeSize2(root.left)+NodeSize2(root.right)+1;
        return tmp;
    }

2.1. 获取叶子结点个数

       叶子结点就是没有左右子树的结点,递推公式为左子树叶子结点加右子树结点,结束条件为结点的左右子树都为空。

    //获取叶子结点个数
    public int getLeafNodeCount(TreeNode root){
        if(root == null){
            return 0;
        }else if(root.left == null && root.right == null){
            return 1;
        }else{
            return getLeafNodeCount(root.left)
                    + getLeafNodeCount(root.right);
        }
    }

    public int LeafCount;

    //遍历问题
    public void getLeafNodeCount2(TreeNode root){
        if(root == null){
            return;
        }
        if(root.left == null && root.right == null){
            LeafCount++;
        }
        getLeafNodeCount2(root.left);
        getLeafNodeCount2(root.right);
    }

2.3. 获取第k层结点的个数

        比如我们要想获取第3层结点的个数,就要求root.left第2层和root.right的第二层,相当于左树的第一层和右树的第一层。当k=1时,已经找到这一层,此时也是递归的结束条件。

    //获取第k层结点的个数
    public int getLevelNodeCount(TreeNode root,int k){
        if(root == null){
            return 0;
        }
        if(k == 1){
            return 1;
        }
        return getLevelNodeCount(root.right,k-1) +
                getLevelNodeCount(root.left,k-1);
    }

2.4. 获取二叉树的高度

         求二叉树的高度,整棵树的高度等于左子树高度的最大值或者右子树高度的最大值加一,当root为空的时候,高度为0。由于我们不知道是左子树高还是右子树高,所以两边都需要遍历。

    //获取二叉树的高度
    public int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }
        int leftH = getHeight(root.left);
        int rightH = getHeight(root.right);
        return Math.max(leftH,rightH) + 1;
    }

2.5. 检测值为value的元素是否存在

        我们先检查根结点是不是,然后再遍历左子树和右子树,当我们找到了val值,直接返回,不用再递归下面了。

    // 检测值为value的元素是否存在
    public TreeNode find(TreeNode root,int val){
        if(root == null){
            return null;
        }
        if(root.val == val){
            return root;
        }
        
        TreeNode leftVal = find(root.left,val);
        if(leftVal != null){
            return leftVal;
        }
        
        TreeNode rightVal = find(root.right,val);
        if(rightVal != null){
            return rightVal;
        }
        
        return null;
    }
public class Solution {
    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        BinaryTree.TreeNode root = binaryTree.CreatTree();
        binaryTree.NodeSize(root);
        System.out.println("结点个数:"+binaryTree.CountSize);
        System.out.println("结点个数:"+binaryTree.NodeSize2(root));
        System.out.println("叶子结点个数:"+binaryTree.getLeafNodeCount(root));
        binaryTree.getLeafNodeCount2(root);
        System.out.println("叶子结点个数:"+binaryTree.LeafCount);
        System.out.println("第3层结点个数:"+binaryTree.getLevelNodeCount(root,3));
        System.out.println("二叉树的高度:"+binaryTree.getHeight(root));
    }
}


http://www.niftyadmin.cn/n/5865829.html

相关文章

链表(LinkedList)面试题

1.1 ​​​​​​203. 移除链表元素 - 力扣(LeetCode) 分析:题目的要求是移除链表中值为val的所有元素,因此这道题需要使用循环解决问题,删除过程需要记录前一个结点的信息,所以需要使用双坐标解决问题。 …

Mysql 主从集群同步延迟问题怎么解决

目录 一、优化主库性能 二、优化从库性能 三、调整复制参数 四、使用半同步复制 五、启用GTID复制 六、增加从库数量 七、监控与报警 八、网络优化 MySQL主从集群同步延迟问题可以通过多种方法来解决。以下是一些具体的解决方案: 一、优化主库性能 增加硬…

数据结构与算法-图论-最短路-单源最短路的建图方式

单源最短路 单源最短路问题是图论中的核心问题之一,在许多领域都有广泛应用. 定义 单源最短路问题是指在一个带权图(可以是有向图或无向图)中,给定一个特定的源点,求解从该源点到图中其余所有顶点的最短路径长度以及…

next.js-学习2

next.js-学习2 1. https://nextjs.org/learn/dashboard-app/getting-started2. 模拟的数据3. 添加样式4. 字体,图片5. 创建布局和页面页面导航 1. https://nextjs.org/learn/dashboard-app/getting-started /app: Contains all the routes, components, and logic …

C#开发——如何捕获异常和抛出异常

一、捕获异常 在 C#中,可以通过“try-catch”块捕获异常,并通过“is”关键字或“as”关键字来判断异常的具体类型。以下是几种常见的方法来判断异常类型: 方法 1:使用“catch”块直接捕获特定类型的异常 在 C#中,可以…

【react】进阶教程02

目录 一、深度性能优化 1. 列表渲染优化(虚拟列表) 2. 使用 Web Workers 处理 CPU 密集型任务 二、复杂状态管理场景 1. 全局状态分层(Context useReducer) 2. 异步状态管理中间件(Redux Thunk) 三、…

【NLP 37、激活函数 ③ relu激活函数】

—— 25.2.23 ReLU广泛应用于卷积神经网络(CNN)和全连接网络,尤其在图像分类(如ImageNet)、语音识别等领域表现优异。其高效性和非线性特性使其成为深度学习默认激活函数的首选 一、定义与数学表达式 ReLU&#xff0…

IDEA创建Spring配置文件Spring Config的方法

作为刚刚开始学Spring框架的小白,而且我也是刚刚学怎么用idea,不会简单的操作也是很正常的是吧。这个问题其实只是我傻傻的不懂,是个很简单的问题,我现在把它记录下来。 在idea创建maven项目后,我们在左边右键新建xml文…