什么是二叉树

2023-11-01

什么是二叉树

什么是二叉树?

  • 树有很多种, 每个节点最多只能有两个子节点的叫二叉树
  • 二叉树的子节点分为左节点和右节点
    avatar
  • 如果二叉树的所有叶子节点都在最后一层, 并且结点总数=2^n-1, n为层数, 则我们称之为满二叉数
    avatar
  • 如果该二叉树的所有叶子节点(没有子节点的节点)都在最后一层或者倒数第二层, 而且最后一层的叶子节点在左边连续, 倒数第二层的叶子节点在右边连续, 我们称之为完全二叉树
    img

遍历二叉树

  • 前序、中序和后序三种遍历方式
  • 前序遍历, 先输出父节点, 再遍历左子树和右子树
  • 中序遍历, 先遍历左子树, 再输出父节点, 再遍历右子树
  • 后序遍历, 先遍历左子树, 再遍历右子树, 最后输出父节点

代码实现

  • Java
/**
 * 1. 定义节点
 */
class HeroNode{
    private int no;
    private String name;
    private HeroNode left;
    private HeroNode right;

    public HeroNode(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode getLeft() {
        return left;
    }

    public void setLeft(HeroNode left) {
        this.left = left;
    }

    public HeroNode getRight() {
        return right;
    }

    public void setRight(HeroNode right) {
        this.right = right;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
    
       /**
     * 前序遍历
     */
    public void preOrder(){
        // 1. 先输出父节点
        System.out.println(this);
        // 2. 递归向左子树前序遍历
        if(this.left != null){
            this.left.preOrder();
        }
        //3. 递归向右子树前序遍历
        if(this.right != null){
            this.right.preOrder();
        }
    }

    /**
     * 中序遍历
     */
    public void midOrder(){
        //1.递归向左子树前序遍历
        if(this.left != null){
            this.left.midOrder();
        }

        //2.先输出父节点
        System.out.println(this);

        //3.递归向右子树前序遍历
        if(this.right != null){
            this.right.midOrder();
        }
    }

        /**
     * 后序遍历
     */
    public void postOrder(){
        //1.递归向左子树前序遍历
        if(this.left != null){
            this.left.postOrder();
        }

        //2.递归向右子树前序遍历
        if(this.right != null){
            this.right.postOrder();
        }

        //3.先输出父节点
        System.out.println(this);
    }

     /**
     * 查找节点
     * @param no
     */
    public HeroNode preOrderSearch(int no){
        //当前节点是不是
        if (this.no == no){
            return this;
        }

        HeroNode  heroNode = null;
        //在左子树找到
        if(this.left != null){
            heroNode = this.left.preOrderSearch(no);
            if (heroNode != null){
                return heroNode;
            }
        }

        //在右子树找到
        if(this.right != null){
            heroNode = this.right.preOrderSearch(no);
            if (heroNode != null){
                return heroNode;
            }
        }
        return null;
    }

      /**
     * 删除节点
     * @param no 要删除节点的ID
     *
     * 思路:
     * 1. 先判断左支节点不为空且是要删除的节点, 就将this.left = null; 返回, 结束遍历;
     * 2. 再判断右支节点不为空且是要删除的节点, 就将this.right = null; 返回, 结束遍历;
     * 3. 如果1,2两步没有删除节点, 那我们就先向左子树进行递归删除
     * 4. 如果第3步页也没有删除节点, 就应当向右子树进行递归删除
     */
    public void delNode(int no){
        // 1.先判断左支节点不为空且是要删除的节点, 就将this.left = null; 返回, 结束遍历;
        if(this.left != null && this.left.no == no){
            this.left = null;
            return;
        }
        //2. 再判断右支节点不为空且是要删除的节点, 就将this.right = null; 返回, 结束遍历;
        if(this.right != null && this.right.no == no){
            this.right = null;
            return;
        }
        //3. 如果1,2两步没有删除节点, 那我们就先向左子树进行递归删除
        if(this.left != null){
            this.left.delNode(no);
        }
        //4. 如果第3步页也没有删除节点, 就应当向右子树进行递归删除
        if (this.right != null){
            this.right.delNode(no);
        }
    }
}

/**
 * 2. 定义二叉树
 */
class BinaryTree{

    private HeroNode root;
    public void setRoot(HeroNode root){
        this.root = root;
    }

    //前序遍历
    public void preOrder(){
        if(this.root != null){
            this.root.preOrder();
        }else{
            System.out.println("二叉树为空, 无法遍历");
        }
    }

    //中序遍历
    public void midOrder(){
        if(this.root != null){
            this.root.midOrder();
        }else{
            System.out.println("二叉树为空, 无法遍历");
        }
    }

    //后序遍历
    public void postOrder(){
        if(this.root != null){
            this.root.postOrder();
        }else{
            System.out.println("二叉树为空, 无法遍历");
        }
    }

    //前序查找
    public HeroNode preOrderSearch(int no){
        if(this.root != null){
            return this.root.preOrderSearch(no);
        }else {
            return null;
        }
    }

    // 删除节点
    public void delNode(int no){
        if(root != null){
            // 判断root节点是不是要删除的节点
            if(root.getNo() == no){
                root = null;
            }else {
                // 递归删除
                root.delNode(no);
            }
        }else {
            System.out.println("空二叉树, 不能删...");
        }
    }
}

/**
 * 3. 测试
 */
public class erCha {
    public static void main(String[] args) {

        // 1. 创建一个二叉树
        BinaryTree binaryTree = new BinaryTree();

        // 2. 创建节点
        HeroNode root = new HeroNode(1, "张三");
        HeroNode node2 = new HeroNode(2, "李四");
        HeroNode node3 = new HeroNode(3, "王五");
        HeroNode node4 = new HeroNode(4, "赵六");
        HeroNode node5 = new HeroNode(5, "宋七");

        //3. 手动创建二叉树
        root.setLeft(node2);
        root.setRight(node3);
        node3.setRight(node4);
        node3.setLeft(node5);
        binaryTree.setRoot(root);

        //4. 遍历
        System.out.println("前序遍历");
        binaryTree.preOrder();
        System.out.println("中序遍历");
        binaryTree.midOrder();
        System.out.println("后序遍历");
        binaryTree.postOrder();

        // 查找节点
        System.out.println("查找节点");
        HeroNode heroNode = binaryTree.preOrderSearch(3);
        System.out.println(heroNode.toString());
    }
}

输出: 
前序遍历
HeroNode{no=1, name='张三'}
HeroNode{no=2, name='李四'}
HeroNode{no=3, name='王五'}
HeroNode{no=5, name='宋七'}
HeroNode{no=4, name='赵六'}
中序遍历
HeroNode{no=2, name='李四'}
HeroNode{no=1, name='张三'}
HeroNode{no=5, name='宋七'}
HeroNode{no=3, name='王五'}
HeroNode{no=4, name='赵六'}
后序遍历
HeroNode{no=2, name='李四'}
HeroNode{no=5, name='宋七'}
HeroNode{no=4, name='赵六'}
HeroNode{no=3, name='王五'}
HeroNode{no=1, name='张三'}
查找节点
HeroNode{no=3, name='王五'}

在这里插入图片描述
雨夜的博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是二叉树 的相关文章

随机推荐

  • python Statsmodel 回归模型笔记

    Statsmodels是Python中一种常用的统计分析库 支持多种回归模型的建立和分析 以下是Statsmodels中常见的几种回归模型及其用途 线性回归模型 Linear Regression Model 用于建立自变量和因变量之间线性
  • 二维线段树的讲解【建立在线段树上的提升】

    二维线段树 二维线段树最主要用于平面统计问题 类似一维线段树 最经典的就是求区间最值 或区间和 推广到二维 求得就是矩形区域最值 或矩形区域和 对于矩形区域和 二维树状数组更加高效 而矩形区域最值 更加高效的方法是二维RMQ 但是二维RMQ
  • Mybatis框架的配置文件总结

    一 Mybatis核心文件的配置 他是有顺序的 固定前缀 额外属性
  • 阿里人机检测验证码的自动化操作尝试

    感谢作者 kunyus 1 通过检测浏览器状态来进行人机检测 使用selenium打开浏览器 通过 selenium 打开的浏览器是出于测试状态的 和正常的浏览器不太一样 通过 selenium 打开的浏览器哪怕人工手动拖动验证码也会被判断
  • PTA 4-7-7 Sigmoid函数及其梯度 (35 分)

    4 7 7 Sigmoid函数及其梯度 35 分 为了方便表述 对于作用于矩阵的激活函数 本文中如果无特殊说明 表示它分别作用于矩阵的每个元素 即f X i j f Xi j 如果没有非线性函数作为激活函数 那么无论多层感知机 MLP 有多
  • js设置随机颜色

    获取随机颜色 16进制 Math floor Math random 16777215 toString 16 eg
  • C语言经典100例题(39)-- 有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。

    目录 题目 问题分析 代码 测试结果 题目 有一个已经排好序的数组 现输入一个数 要求按原来的规律将它插入数组中 问题分析 首先判断此数是否大于最后一个数 然后再考虑插入中间的数的情况 插入后 此元素之后的数 依次后移一个位置 代码 inc
  • Ubuntu安装腾讯会议及运行腾讯会议的命令 亲测有用

    运行腾讯会议的命令 A A Dell G15 5511 opt wemeet wemeetapp sh 参考 Ubuntu安装腾讯会议 Ubuntu16 04 18 04 20 04 22 04 ubuntu下载腾讯会议 HIT Vanni
  • 人脸检测、人脸对齐(MTCNN方法)

    众所众知 严格定义上的人脸识别分为四个步骤 人脸检测 从图片中准确定位到人脸 人脸矫正 对齐 检测到的人脸 可能角度不是很正 需要使其对齐 对矫正后的人脸进行特征提取 对两张人脸图像的特征向量进行对比 计算相似度 这里 我们主要是推荐步骤1
  • How to fix hung_task_timeout_secs and blocked for more than 120 seconds problem

    Author Skate Time 2015 03 04 How to fix hung task timeout secs and blocked for more than 120 seconds problem 现象 系统hang住
  • 执行bin/schematool -initSchema -dbType mysql -verbos 初始化hive报错SQL Error code: 1045

    报错原因 执行命令 bin schematool initSchema dbType mysql verbos 报错信息 SLF4J Class path contains multiple SLF4J bindings SLF4J Fou
  • 苹果“屈服”了?App Store 竟允许第三方支付!

    整理 郑丽媛 出品 CSDN ID CSDNnews 苹果和 Epic Games 之间的矛盾想必大家都有所了解 Epic Games 旗下一款游戏 堡垒之夜 因不想被抽取 30 的 苹果税 绕过苹果内购 IAP In App Purcha
  • SQL Server 修改字段属性为 NOT NULL,并设置默认值

    修改字段 NULL gt NOT NULL alter table ndb adshow alter column shopid1 int not null 设置 修改默认值 一 如果没有设置默认值 则直接执行下面语句 alter tabl
  • sqli-labs (less-34)

    sqli labs less 34 进入34关 我们发现又回到了我们熟悉的页面 我们直接输入用户名和密码登入进去 像之前的关卡一样 我们输入的用户名和密码也是使用POST的方式传输到了服务器 所以我们继续使用hackbar工具抓取POST内
  • OpenWrt :添加OpenWrt软件包

    12 1简介 OpenWrt是一个比较完善的嵌入式Linux开发平台 在无线路由器应用上已有4000多个软件包 我们可以在其基础上增加软件包 以扩大其应用范围 在OpenWrt中增加软件包极其方便 按照OpenWrt的约定就可以很简单的完成
  • SPWM的单极性和双极性

    单极性 双极性 只包含了正弦信号正半周或负半周的信息 既包含了正弦信号正半周的信息 又包含了负半周的信息 一般用推挽或全桥 一般用于半桥 反应在推挽上 反应在逆变桥上 两管交替按10MS的时间导通 但是导通的管 在10MS内按三角波的频率导
  • hi3861使用iic驱动adxl346

    开发平台 Ubuntu 18 04 DOPI hi3861lv开发板 adxl346模组 Q群 735884031 一 配置3861iic 1 搭建demo工程 可参考我的上一篇博客 2 查看引脚复用 使用GPIO9 GPIO10作为iic
  • mysql-8.0.16-winx64安装教程

    一 MySQL数据库安装 本篇文章主要介绍mysql 8 0 16 winx64的安装方法 zip压缩包我放到了我的资源里 需要的可以自行下载 官网下载地址 具体安装方法如下 1 选择你自己的安装路径 我放在了D盘的MySQL目录下 D M
  • Android 底部导航栏(底部Tab)最佳实践(附带学习源码)

    当开始一个新项目的时候 有一个很重要的步骤就是确定我们的APP首页框架 也就是用户从桌面点击APP 图标 进入APP 首页的时候展示给用户的框架 比如微信 展示了有四个Tab 分别对应不同的板块 微信 通讯录 发现 我 现在市面出了少部分的
  • 什么是二叉树

    什么是二叉树 什么是二叉树 树有很多种 每个节点最多只能有两个子节点的叫二叉树 二叉树的子节点分为左节点和右节点 avatar 如果二叉树的所有叶子节点都在最后一层 并且结点总数 2 n 1 n为层数 则我们称之为满二叉数 avatar 如