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

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

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 树,红黑树。

相关文章
|
8月前
|
存储 算法 Java
算法系列之数据结构-二叉树
树是一种重要的非线性数据结构,广泛应用于各种算法和应用中。本文介绍了树的基本概念、常见类型(如二叉树、满二叉树、完全二叉树、平衡二叉树、B树等)及其在Java中的实现。通过递归方法实现了二叉树的前序、中序、后序和层次遍历,并展示了具体的代码示例和运行结果。掌握树结构有助于提高编程能力,优化算法设计。
251 10
 算法系列之数据结构-二叉树
分享一些提高二叉树遍历算法效率的代码示例
这只是简单的示例代码,实际应用中可能还需要根据具体需求进行更多的优化和处理。你可以根据自己的需求对代码进行修改和扩展。
311 64
|
10月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
269 12
|
10月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
187 10
|
10月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
386 3
|
11月前
|
存储 算法 Python
文件管理系统中基于 Python 语言的二叉树查找算法探秘
在数字化时代,文件管理系统至关重要。本文探讨了二叉树查找算法在文件管理中的应用,并通过Python代码展示了其实现过程。二叉树是一种非线性数据结构,每个节点最多有两个子节点。通过文件名的字典序构建和查找二叉树,能高效地管理和检索文件。相较于顺序查找,二叉树查找每次比较可排除一半子树,极大提升了查找效率,尤其适用于海量文件管理。Python代码示例包括定义节点类、插入和查找函数,展示了如何快速定位目标文件。二叉树查找算法为文件管理系统的优化提供了有效途径。
186 5
|
11月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
12月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
297 4
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
849 8
|
存储 缓存 算法
如何提高二叉树遍历算法的效率?
选择合适的遍历算法,如按层次遍历树时使用广度优先搜索(BFS),中序遍历二叉搜索树以获得有序序列。优化数据结构,如使用线索二叉树减少空指针判断,自定义节点类增加辅助信息。利用递归与非递归的特点,避免栈溢出问题。多线程并行遍历提高速度,注意线程安全。缓存中间结果,避免重复计算。预先计算并存储信息,提高遍历效率。综合运用这些方法,提高二叉树遍历算法的效率。
307 5