数据结构与算法——二叉树(下)

羊祜
• 阅读 1123
1. 概述

前面的文章说到了二叉树,其实今天讲的二叉搜索(查找)树就是二叉树最常用的一种形式,它支持高效的查找、插入、删除操作,它的定义是这样的:对于树中的任意一个节点,其左子节点值必须小于该节点,其右子节点必须大于该节点。例如下图中的几种树都是二叉查找树:

数据结构与算法——二叉树(下)

2. 二叉搜索树的查找

我们直接拿查找的数据和根节点数据作比较,如果大于根节点,则在右子树中递归查找,如果小于根节点,则在左子树中查找,如果等于,则直接返回。就像下图的查找过程:

数据结构与算法——二叉树(下)

结合代码能够更直观的理解:

public class BinaryTree {
    private Node head = null;//树的根节点
    //1.查找节点
    public Node find(int value){
        Node p = head;
        while (p != null){
            if (p.getData() > value) p = p.left;
            else if (p.getData() < value) p = p.right;
            else return p;
        }
        return null;
    }
    //定义树的节点
    public static class Node{
        private int data;
        private Node left;
        private Node right;

        public Node(int data) {
            this.data = data;
            this.left = null;
            this.right = null;
        }

        public int getData() {
            return data;
        }
    }
}
3. 二叉搜索树的插入

插入操作和查找其实比较的类似,都是需要拿插入的数据和树中的数据进行比较,如果插入的数据大于树节点数据,并且节点的右子树为空,则直接插入到右子树,否则继续在右子树中递归查找位置;如果插入的数据小于树节点数据,并且节点的左子树为空,则直接插入到左子树,否则继续在左子树中递归查找位置。

数据结构与算法——二叉树(下)

结合代码理解一下:

 public void insert(int value){
        Node node = new Node(value);
        if (head == null){
            head = node;
            return;
        }
        Node p = head;
        while (p != null){
            if (p.getData() > value){
                if (p.left == null) {
                    p.left = node;
                    return;
                }
                p = p.left;
            }
            else {
                if (p.right == null) {
                    p.right = node;
                    return;
                }
                p = p.right;
            }
        }
    }
4. 二叉搜索树的删除

前面的查找和插入操作都比较的简单易懂,但是二叉搜索树的删除操作就比较的复杂了,分为了几种情况。

  • 第一种情况:要删除的节点没有子节点,这样的话,可以直接将指向该节点的父节点指针设为 null。
  • 第二种情况:要删除的节点只有一个子节点,直接将该节点的父节点的指针,指向该节点的子节点即可。
  • 第三种情况:要删除的节点有两个子节点,我们需要在删除节点的右子树中,寻找到最小的那个节点,然后将其放在删除的节点的位置上。

三种情况对应下图:

数据结构与算法——二叉树(下)

结合代码来理解一下:

    //3.删除数据
    public void delete(int value){
        Node p = head;
        Node pParent = null;//p节点的父节点

        //先找到这个节点
        while (p != null && p.getData() != value){
            pParent = p;
            if (p.getData() > value)p = p.left;
            else p = p.right;
        }
        if (p == null) return;//表示没有找到值为value的节点

        //1.假如要删除的节点有两个子节点
        if (p.left != null && p.right != null){
            //查找p节点的右子节点中的最小值
            Node minP = p.right;
            Node minPP = p;//minPP表示minP的父节点
            while (minP.left != null){
                minPP = minP;
                minP = minP.left;
            }
            p.data = minP.getData();
            if (minPP == p) p.right = null;
            else minPP.left = null;
            return;
        }

        //2.假如删除的节点p是叶子节点或只有一个子节点
        Node child = null;
        if (p.left != null) child = p.left;
        else if (p.right != null) child = p.right;

        if (pParent == null) head = child;
        else if (pParent.left == p) pParent.left = child;
        else pParent.right = child;
    }
5. 二叉搜索树分析

最后,还有两个需要说明一下,前面说到了二叉树的三种遍历方式,其中,中序遍历的方式是先遍历节点的左子节点,再遍历这个节点本身,然后遍历节点的右子节点。所以,如果中序遍历二叉搜索树,会得到一个有序的数据,时间复杂度是 O(n),所以二叉搜索树又叫做二叉排序树

在理想的情况下,我们的二叉树是一棵满二叉树或者完全二叉树,那么查找、插入、删除操作十分的高效,时间复杂度是 O(logn),但是,如果二叉树的左右子树非常的不平衡,极端的情况下,可能会退化为链表,那么性能就下降了。

所以,我们需要一种方式来维持二叉树的平衡,最好是将其维持为满二叉树或者完全二叉树,这就是后面会说到的平衡二叉查找树,常见的有 AVL 树,红黑树。

点赞
收藏
评论区
推荐文章
白茶清欢 白茶清欢
4年前
js实现二叉树、二叉查找树
树是一种数据结构,该章节讨论二叉树(二叉树的每个节点的子节点不允许超过两个),二叉树中有又分为完全二叉树和不完全二叉树.....不在本章节赘述相关概念,感兴趣可以去查阅《数据结构》。你将会获得:1.如何使用js实现二叉查找树。2.学会前、中、后序遍历。3.了解相关实现原理阅读时长5min,可选择直接调试代码特点    二叉查找树中序遍历后
似梦清欢 似梦清欢
2年前
树与二叉树
二叉树层次建树二叉树(BinaryTree)是由有限个结点组成的集合,它或者为空集合,或者仅含一个根结点,或者由一个根结点和两棵互不相交的左、右子树组成。树为空即根节点为空。二叉树的基本形态如下图:a:空的二叉树,treeNULL。b:只有空节点的二叉树,
Wesley13 Wesley13
3年前
JAVA递归实现线索化二叉树
JAVA递归实现线索化二叉树基础理论首先,二叉树递归遍历分为先序遍历、中序遍历和后序遍历。先序遍历为:根节点左子树右子树中序遍历为:左子树根节点右子树后序遍历为:左子树右子树根节点(只要记住根节点在哪里就是什么遍历,且都是先左再右)线索化现在有这么一棵二叉树,它的数据结
Stella981 Stella981
3年前
LeetCode(98): 验证二叉搜索树
Medium!题目描述:给定一个二叉树,判断其是否是一个有效的二叉搜索树。一个二叉搜索树具有如下特征:节点的左子树只包含小于当前节点的数。节点的右子树只包含大于当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。示例 1:输入:2/\
Wesley13 Wesley13
3年前
PHP数据结构与算法:二叉树
一、定义二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(leftsubtree)和“右子树”(rightsubtree)。二、特性1.在二叉树的第i层上至多有2^(i1)个结点(i0)2.深度为k的二叉树至多有2^k1个结点(k0)3.对于任意一棵二叉树,如果其叶结点数为N0,而
Stella981 Stella981
3年前
LeetCode初级算法之树:98 验证二叉搜索树
01题目信息题目地址:https://leetcodecn.com/problems/validatebinarysearchtree/给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:节点的左子树只包含小于当前节点的数。
Wesley13 Wesley13
3年前
B
BTreeBTree又叫做B树,和平衡二叉树不同的地方在于B树是多叉树(平衡多路查找树),Oracle和MongoDB的索引技术就是基于B树的数据结构,B树也可以看作是对23查找树的一种扩展。一个m阶的BTree有以下性质1.每个节点最多有m个子节点;2.每个非叶子节点(根节点除外)至少含有m/2个子节点;3.
Wesley13 Wesley13
3年前
98. 验证二叉搜索树
题目描述给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:节点的左子树只包含小于当前节点的数。节点的右子树只包含大于当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。输入:5/\14 /\ 
贾蔷 贾蔷
2个月前
力扣501题 解题思路和步骤 C++代码实现,力扣(leetcode)
问题背景及描述力扣501题要求我们找出在一个二叉搜索树(BST)中的众数。二叉搜索树是一种特殊的二叉树,其中每个节点的值都大于其左子树中的任何节点,且小于其右子树中的任何节点。众数是指在BST中出现次数最多的值。解题思路分析解题的关键在于理解BST的性质以
贾蔷 贾蔷
1个月前
手搓二叉树构建类代码详解:从入门到实践(适合新手小白)
一、简介和应用二叉树是数据结构中常见的一种树形结构,每个节点最多有两个子节点(左子节点和右子节点)。它广泛应用于算法设计、数据存储与搜索(如二叉搜索树)、表达式解析等领域。本文将通过手写的C代码,讲解如何构建一个基础的二叉树类,帮助新手理解其原理与实现
深度学习 深度学习
3星期前
手把手教你实现二叉树:从代码注释到实战应用
一、简介和应用是一种经典的,它由节点组成,每个节点最多有两个子节点(左子节点和右子节点)。这种结构因其简洁性和高效性被广泛应用于设计、数据存储与检索等领域。例如,文件系统目录结构、搜索算法(如)以及表达式解析树等场景都离不开二叉树。对于编程新手来说,理解二
羊祜
羊祜
Lv1
疏影横斜水清浅,暗香浮动月黄昏。
文章
4
粉丝
0
获赞
0