一文读懂二叉树

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。

什么是二叉树

二叉树是一种由节点(Node)组成的数据结构,每个节点最多有两个子节点。它具有良好的层次结构,便于搜索和遍历。二叉树的定义和操作方法可以通过面向对象的方式来理解,每个节点都是一个对象,节点之间通过引用关系连接。

常见的二叉树有哪些

  1. 满二叉树
  2. 完全二叉树
什么是满二叉树

如图所示:

在这里插入图片描述
这棵二叉树为满二叉树,也可以说深度为k,有2^k-1个节点的二叉树。根节点为 k = 1 的深度开始计算,如图所示的二叉树,它的深度为 4 ,所以这棵满二叉树有15个节点。

什么是完全二叉树

完全二叉树中,除了最底层节点以外,其余每层节点数都达到最大值,并且最下面一层的节点从左到右是连续的,这样的二叉树为完全二叉树。

如图1所示:最底部的节点数从左至右是连续的,该树为完全二叉树

在这里插入图片描述
如图2所示:从左至右是连续的,因此也是完全二叉树

在这里插入图片描述

如图3所示:最底部的节点不是连续的,该树不是一个完全二叉树

在这里插入图片描述

什么是二叉搜索树

前面介绍的树,都没有数值的,而二叉搜索树是有数值的了,二叉搜索树是一个有序树。

  1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  3. 它的左、右子树也分别为二叉排序树

如图所示:这棵树就是一颗二叉搜索树

在这里插入图片描述

什么是平衡二叉搜索树

平衡二叉搜索树:又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

它通过在插入和删除节点时进行旋转操作来保持树的平衡。AVL树的平衡因子(左子树高度减去右子树高度的差值)在范围[-1, 1]之间。

如图所示:这是一颗平衡二叉树,它的左右两个树的高度差在为1

在这里插入图片描述

如图所示:它的高度差为1,因此也是一个平衡二叉搜索树

在这里插入图片描述

如图所示:它的高度差已经大于1了,这不是一棵平衡二叉搜索树

在这里插入图片描述

二叉搜索树的存储方式

二叉搜索树的存储方式主要有两种:链式存储和数组存储。

  1. 链式存储:
    在链式存储方式中,每个节点由一个对象(或结构体)表示,并包含指向其左子节点和右子节点的指针(或引用)。每个节点的结构可以包含一个键(用于比较和排序)以及其他相关数据。
    优点:
    灵活性:链式存储方式可以动态地分配内存,并且可以根据需要插入、删除节点,使得树的结构可以动态变化。
    插入和删除效率高:由于节点的指针连接,插入和删除操作只需要改变指针的指向,效率较高。
    缺点:
    需要额外的指针空间:每个节点需要存储左子节点和右子节点的指针,占用额外的空间。
    指针操作可能增加内存开销:在大规模数据集的情况下,节点对象和指针操作可能导致额外的内存开销。

如图所示:链式存储

在这里插入图片描述

  1. 数组存储:
    在数组存储方式中,使用一个数组来表示二叉搜索树的结构。数组的索引位置对应着节点的顺序,节点的值存储在数组中的对应位置。
    优点:
    内存连续:数组存储方式使用连续的内存空间,可以减少指针操作的开销。
    访问效率高:通过数组的索引可以直接访问节点,查找效率较高。
    缺点:
    静态结构:数组存储方式需要预先确定数组的大小,无法动态调整树的结构,因此不适用于频繁的插入和删除操作。
    内存空间浪费:如果树的大小不确定,可能会浪费一部分数组空间。

    如图所示:数组存储

    在这里插入图片描述

在这里插入图片描述
如果父节点的数组下标是 i,那么它的左孩子就是 i * 2 + 1,右孩子就是 i * 2 + 2。

但是用链式表示的二叉树,更有利于我们理解,所以一般我们都是用链式存储二叉树。

二叉树的遍历

二叉树主要有两种遍历方式:

  1. 深度优先遍历:先往深走,遇到叶子节点再往回走,一条路走到黑,走到最低部再回退回来。
    前序遍历(递归法,迭代法)
    中序遍历(递归法,迭代法)
    后序遍历(递归法,迭代法)
  2. 广度优先遍历:一层一层的去遍历。
    层次遍历(迭代法)
什么是前序遍历

前序遍历就是从根节点开始,先遍历中间节点,在遍历左节点(同时左节点又分为中-》左-》右),最后遍历右节点(同时右节点又分为中-》左-》右)

如图所示:
这棵树前序遍历的结果是:10 5 2 8 15 13 16

在这里插入图片描述

什么是中序遍历

同理,中序遍历就是先遍历左节点(同时左节点分为左中右),再遍历中节点,最后遍历右节点(右节点也按照左中右来遍历)

如上图所示:
中序遍历结果是:2 5 8 10 13 15 16

什么是后续遍历

同理,后续遍历就是先遍历左节点(同时左节点分为左右中),再遍历右节点(右节点也按照左右中国来遍历),最后处理中间节点

如上图所示:
后续遍历结果是:2 8 5 13 16 15 10

通过上面的遍历结果其实可以了解到,前中后序遍历对应的中间节点的位置分别为前中后,所以前中后序遍历代表着中间节点所对应的位置。

手写一个二叉搜索树

不废话,上代码:

public class TreeNode {
    int val; // 数值

    TreeNode left; // 左指针,指向左孩子

    TreeNode right; // 右指针,指向右孩子

    public TreeNode() {

    }

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

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

备注:笔记整理,部分图片来自《代码随想录》,深度学习所整理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是三叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值