【数据结构】二叉树的原理及实现

news2025/7/19 7:23:00

1.什么是数?

  • 树这种数据结构在计算机中是非常重要的,是一种非线性数据结构。一些数据库的底层与快速索引都离不开树这种数据结构。
  • 树是有很多节点组成的具有一定层次关系的集合。最上面的可以看成是树的头,下面的很多节点就在这个头的基础上不断的向下延伸,类似一颗倒挂的树。
  • 树是由n>=0个结点的有限集,当n=0的时候,这个树被叫做空树。当n>1的时候,表明它是一颗非空的树,在一颗非空的树里面。

在这里插入图片描述

  • 树的特点

    • 在每一个节点会有0个或者0个以上的子节点
    • 没有父节点的节点被称为根节点
    • 非根节点只有一个父节点
    • 每个节点的子节点整体上来看像一颗倒挂的树,也被称为父节点子树。
  • 树的专业术语

    • 节点:是指数据元素和指向子树的分支
    • 根节点:在非空树中没有前驱结点的结点,被称为根节点(注意,只有一个根节点)
    • 节点的度:结点所拥有子树个数
    • 树的度:树里的各个节点度的最大值
    • 父节点:A是B的父节点
    • 子节点:B是A的子节点
    • 叶子节点:当度等于0的时候被称为叶子节点。
    • 路径:从根节点找该节点的路径,比如要找K节点。路径为:A->C->G->K
    • 层:同一个层面为一层。如A为1层,BC为2层

2.二叉树基本概念

  • 什么是二叉树

    • 树有很多种,但是每一个结点最多只有两个子节点的树,被称作为二叉树。
    • 二叉树的子节点又分成左节点与右节点
    • 二叉树又分为满二叉树与完全二叉树
  • 满二叉树

    • 概念为:如果这颗二叉树的所有叶子节点都在该树的最后一层的话,并且节点的总数=2^n-1(n为层数)。
    • 节点总数=2^4-1=15

在这里插入图片描述

  • 完全二叉树

    • 概念:当前二叉树所有的叶子节点再倒数第一层或者是倒数第二层当中,而且的话最后一层的叶子节点是在左边连续的,而在倒数第二层的叶子节点是右边连续的。

    • 如果把G节点删除的话,它就不属于完全二叉树了,因为它的叶子结点已经是不连续了。

在这里插入图片描述

  • 二叉排序树

    • 概念:也叫作二叉查找树。二叉排序树的任何一个非叶子节点,都要求他的左子节点的值要比当前的节点值小,右子节点值要比当前的节点值大。

    • 排序树的左子树不为空,那么左子树的所有节点都小于他根节点的值

    • 他的右子树不为空,那么右子树的所有节点的值都大于它根节点的值

在这里插入图片描述

3.二叉树的前中后续遍历

  • 二叉树的遍历

    • 在学数组的时候,需要查找某一个值的时候,是不是需要遍历数据来查找的。
  • 那在树结构查找某一个值的时候,它与线性结构不一样,没有办法从头开始遍历,那它是如何进行遍历的呢?

在这里插入图片描述

我们可以把上图的树分成根节点、左子树和右子树。再根据根节点什么时候被访问,我们就把二叉树遍历分成三种方式

  • 前序遍历:首先访问根节点,然后先是访问左子树,最后才到右子树。
    • 6 4 2 1 3 5 9 8 11
  • 中序遍历:首先访问左子树,然后到根节点,最后才到右子树。
    • 1 2 3 4 5 6 8 9 11
  • 后序遍历:首先访问左子树,然后到右子树,最后到根节点。
    • 1 3 2 6 4 8 11 9 6

4.排序二叉树实战

public class BinaryTree {

    //创建根节点
    public Node root;

    /**
     * 查看二叉树
     * @return
     */
    public Node getRoot(){
        return root;
    }

    /**
     * 求二叉树的最大深度
     * @param root
     * @return
     */
    public int maxDep(Node root){
        //根节点是否为空
        if(root == null) return 0;
        return Math.max(maxDep(root.left),maxDep(root.right))+1;
    }

    /**
     * 查找二叉树节点
     * @param id
     * @return
     */
    public String get(Node root,int id){
        //判断根节点是否为null
        if(root == null){
            return "";
        }
        //判断传入的ID是否是小于根节点
        if(id < root.id){
            return get(root.left,id);
        }
        //判断传入的ID是否大于根节点
        if(id > root.id){
            return get(root.right,id);
        }
        return root.name;
    }

    /**
     * 二叉树添加节点
     * @param node
     */
    public void add(Node node){
        //先判断根是否为null
        if(root == null){
            root = node;
        }else{
            root.add(node);
        }
    }

    /**
     * 前序遍历
     */
    public void preTraversal(){
        getRoot().preTraversal();
    }

    /**
     * 中序遍历
     */
    public void infixTraversal(){
        getRoot().infixTraversal();
    }

    /**
     * 后续遍历
     */
    public void postTraversal(){
        getRoot().postTraversal();
    }

    static class Node{
        //定义ID
        private int id;
        //定义name
        private String name;
        //定义左节点
        private Node left;
        //定义右节点
        private Node right;
        //初始化节点的值
        public Node(int id,String name){
            this.id = id;
            this.name = name;
        }

        /**
         * 添加节点
         * @param node
         */
        public void add(Node node){
            //首先先判断node是否为null
            if(node == null){
                return;
            }
            //判断是否比根小,向左插入
            if(node.id<this.id){
                if(this.left == null){
                    this.left = node;
                }else{
                    this.left.add(node);
                }
            }
            //判断是否比根大,向右插入
            if(node.id>this.id){
                if(this.right == null){
                    this.right = node;
                }else{
                    this.right.add(node);
                }
            }
        }

        /**
         * 前序遍历
         */
        public void preTraversal(){
            //输出根节点
            System.out.println("id:"+this.id+",name:"+this.name);
            //输出左节点
            if(this.left!=null){
                this.left.preTraversal();
            }
            //输出右节点
            if(this.right!=null){
                this.right.preTraversal();
            }
        }

        /**
         * 中序遍历
         */
        public void infixTraversal(){
            //输出左节点
            if(this.left!=null){
                this.left.infixTraversal();
            }
            //输出根节点
            System.out.println("id:"+this.id+",name:"+this.name);
            //输出右节点
            if(this.right!=null){
                this.right.infixTraversal();
            }
        }

        /**
         * 后续遍历
         */
        public void postTraversal(){
            //输出左节点
            if(this.left!=null){
                this.left.postTraversal();
            }
            //输出右节点
            if(this.right!=null){
                this.right.postTraversal();
            }
            //输出根节点
            System.out.println("id:"+this.id+",name:"+this.name);
        }
    }

    public static void main(String[] args) {

        BinaryTree binaryTree = new BinaryTree();

        int [] arr = {4,2,9,7,1,5};
        // 向树中添加元素
        for (int i = 0; i < arr.length; i++) {
            binaryTree.add(new Node(arr[i], "李祥"+i));
        }

        // 前序遍历
        System.out.println("前序遍历:");
        binaryTree.preTraversal();
        // 中序遍历
        System.out.println("中序遍历:");
        binaryTree.infixTraversal();
        // 后序遍历
        System.out.println("后序遍历:");
        binaryTree.postTraversal();

        //快速查找二叉树中的元素
        System.out.println("查找节点为 2 的元素:"+binaryTree.get(binaryTree.getRoot(), 2));

        //查询二叉树的最大深度
        System.out.println("二叉树的最大深度:"+binaryTree.maxDep(binaryTree.getRoot()));
    }

}

在这里插入图片描述

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

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

相关文章

前端如何实现局部滚动效果?

一、基础版局部滚动 重点在于给需要滚动的区域加上 overflow: auto; 属性 废话不多说&#xff0c;先上基础版的局部滚动代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http-equiv…

智能优化算法——遗传算法(GA)(纯理论,不包含代码)

今天接着PSO&#xff0c;记录一下遗传算法的实现原理。&#xff08;若有错误&#xff0c;请大佬帮忙指正&#xff01;&#xff09;&#xff08;同样&#xff0c;主要参考b站视频学习加入自己的一些理解&#xff0c;如果想要看视频学习&#xff0c;可以直接移步最后参考链接&…

深度学习引言

动手学深度学习pytorch版-笔记原文链接日常生活中的机器学习机器学习中的关键组件数据模型目标函数优化算法各种机器学习问题监督学习回归分类标记问题搜索推荐系统序列学习无监督学习与环境互动强化学习特点小结原文链接 动手学深度学习pytorch中文版 日常生活中的机器学习 …

可怕,chatGPT用3小时教会我数据分析

chatGPT这玩意真的是我的救星,用它作为我的Python教练,我用三个小时学会了数据处理(Pandas)和绘图(matplotlib)。 这两个库的学习,在之前已经困扰了我7个月。之前卡壳的原因,是我一直没有耐心从零开始,按照教材设置的教程去学习Python——我擅长在项目中学习,一点一点…

Android实现炫酷跳动的闪屏LOGO

前言&#xff1a;在日常开发中&#xff0c;经常会遇到各种视觉效果&#xff0c;有的效果可能一眼看去会让人觉得很复杂&#xff0c;但是我们必须明确一点&#xff1a;所有复杂动效都是可以分解成单一的基础动作&#xff0c;比如缩放&#xff0c;平移&#xff0c;旋转这些基础单…

最新BlackArch发布,提供1400款渗透测试工具

近日&#xff0c;BlackArch Linux新版本发布&#xff0c;此版本为白帽子和安全研究人员提供了大约1400款渗透测试工具&#xff0c;如果你是一位白帽子或者安全研究人员&#xff0c;这个消息无疑会让你很感兴趣。BlackArch Linux是一款基于Arch Linux的发行版&#xff0c;主要面…

luckysheet的使用——07.二次开发自动插入批注功能

在单元格编辑完成后&#xff0c;需要自动在这个单元格上新增批注&#xff0c;此时需要改造旧代码&#xff0c;首先找到路径为 src/controllers/postil.js的文件&#xff0c;找到新增批注时触发的方法&#xff0c;如下&#xff1a; 2.对方法进行改造&#xff0c;新增传入变量co…

深入探讨下,IPC产品与智能家居融合的无限开创性

IPC还有哪些新玩法&#xff1f;随着摄像头的应用场景增加&#xff0c;IPC作为一种能力&#xff0c;正在融入到越来越多的智能设备中&#xff0c;形成了一批富有创意的智能 IPC 融合类产品。 比如&#xff0c;扫地机结合智能 IPC 后&#xff0c;能实现可视化精准识别障碍物&…

C++实现日期类

文章目录前言1.日期类的功能分析1.大致分析2.接口设计2.具体实现1.日期类的成员函数和成员变量2.初始化(构造函数&#xff09;3.对日期进行天数推算4.比较相关的运算符重载5.前置后置自增或自减6.日期相减与流插入流提取1.日期相减2.重载流插入和流提取3.总结前言 之前介绍了C…

数据结构与算法—链表list

目录 链表 链表类型 链表插入 链表删除 写程序注意点 与数组区别 链表应用 LRU 实现思想 链表 链表&#xff0c;一种提高数据读取性能的技术&#xff0c;在硬件设计、软件开发中有广泛应用。常见CPU缓存&#xff0c;数据库缓存&#xff0c;浏览器缓存等。缓存满时&#…

mongoDB5以上实现单机事务

原理就是因为目前mongodb只有副本&#xff0c;分片支持事务。我们就让单机变成单节点副本&#xff0c;同时又是主节点&#xff0c;可以读写一、修改bin目录下的mongod.cfg新增配置replication:replSetName: rs0二、重启mongodb服务、初始化&#xff08;这是windows下的启动命令…

2月24日作业

题目&#xff1a;通过操作Cortex-A7核&#xff0c;串口输入相应的命令&#xff0c;控制LED灯进行工作--->上传CSDN 1.例如在串口输入led1on,开饭led1灯点亮 2.例如在串口输入led1off,开饭led1灯熄灭 3.例如在串口输入led2on,开饭led2灯点亮 4.例如在串口输入led2off,开饭led…

day20_Map

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、比较器排序 三、Collections 四、Map 五、HashMap 六、TreeMap 零、 复习昨日 HashSet 不允许重复元素,无序 HashSet去重原理: 先比较hashco…

Java知识复习(二)Java集合

1、List、Set和Map的区别 List&#xff1a;存储的顺序是有序的、可重复的Set&#xff1a;存储的顺序是无序的、不可重复的Map&#xff1a;使用键值对存储&#xff0c;Key和Value都是无序的&#xff0c;其中Key不可重复&#xff0c;而Value可重复 2、ArrayList和LinkedList的区…

node报错

记录bug:运行 npx -p storybook/cli sb init 时报错gyp info spawn C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exegyp info spawn args [gyp info spawn args build/binding.sln,gyp info spawn args /nologo,gyp info spawn args…

OpenCV只含基本图像模块编译

编译OpenCV4.5.5只含基本图像模块&#xff0c;环境为Windows10 x64CMake3.23.3VS2019。默认编译选项编译得到的OpenCV库往往大几百MB甚至上GB&#xff0c;本文配置下编译得到的库压缩后得到的zip包大小仅6.25MB&#xff0c;适合使用OpenCV基本图像功能模块的项目移植而不牵涉其…

电子技术——伯德图与反馈

电子技术——伯德图与反馈 增益和相位边距 从上两节我们知道环路增益 AβA\betaAβ 可以决定一个系统的稳定性&#xff0c;一个更加简单和有效的方法是我们可以绘制 AβA\betaAβ 的伯德图&#xff08;因为相位可以达到360度&#xff0c;因此这是一个四阶响应系统&#xff09;…

行锁、表锁、主键外键、表之间的关联关系

Java知识点总结&#xff1a;想看的可以从这里进入 目录2.4、行锁、表锁2.5、主键、外键2.5.1、主键2.5.2、外键2.6、表的关联关系2.4、行锁、表锁 MyISAM默认采用表级锁&#xff0c;InnoDB默认采用行级锁。 表锁&#xff1a;开销小&#xff0c;加锁快&#xff0c;不会出现死锁…

KTV「消亡史」:辉煌、挫折与新生

【潮汐商业评论/原创】这是Ina工作的第五年&#xff0c;疫情之后&#xff0c;第一场大学同学聚会就定在了周末。同学群里大家热烈地讨论着聚会的地点&#xff0c;“要不咱们去KTV吧&#xff0c;哈哈哈哈哈哈”&#xff0c;突然有人提议到。“谁还去KTV啊”“多没意思啊”……随…

按字典序排列的最小的等价字符串[拆解并查集]

并查集前言一、按字典序排列的最小的等价字符串二、并查集总结参考文献前言 并查集有什么用&#xff1f;并查集是什么&#xff1f;搞懂这两个问题&#xff0c;相关的并查集问题就变得非常easy&#xff01; 一、按字典序排列的最小的等价字符串 二、并查集 有一种方法&#x…