【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(一)

简介: 【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现

一、二叉搜索树概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
  • 现阶段二叉搜索树没有重复的数据

二、二叉搜索树的创建

2.1 二叉搜索树的基本单位

template<class K>
    struct  BSTreeNode
    {
        BSTreeNode(const K& key = K())
            :_left(nullptr)
                , _right(nullptr)
                , _key(key)
            {}
        BSTreeNode<K>* _left;
        BSTreeNode<K>* _right;
        K _key;
    };

2.2 实现二叉搜索树的基本框架

template<class K>
    class  BSTree
    {
        public:
        //类型名字太长,不方便
        typedef BSTreeNode<K> Node;
        private:
        Node* _root = nullptr;
    };

上面图示以物理结构数组int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13}创建出来的逻辑结构二叉搜索树的数据结构。

2.3 二叉搜索树的查找

二叉搜索树查找步骤:

  • 规定一个关键值key
  • 从根开始开始比较查找,key比根大则往右边走查找,key比根小则往左边走查找
  • 最多查找高度次,走到到空,还没有找到,这值不存在
  • 在插入接口中,虽然查找合适位置代码逻辑差不多,但是存在个别逻辑差异,注意识别
bool Find(const K& key)
{
    Node* cur = _root->_key;
    while (cur)
    {
        if (key < cur->_key)
        {
            cur = cur->_left;
        }
        else if(key > cur->_key)
        {
            cur = cur->_right;
        }
        else
        {
            return true;
        }
    }
    return  false;
}

2.4 二叉搜索树的插入

插入具体过程:

  • 树为空,则直接新增节点,赋值给root指针
  • 树不为空,按二叉搜索树性质插入位置,插入新节点

bool Insert(const K& key)
{
    if (_root == nullptr)
    {
        _root = new Node(key);
        return true;
    }
    Node* parent = nullptr;
    //这里cur是临时变量
    Node* cur = _root;
    while (cur)
    {
        if (cur->_key < key)
        {
            parent = cur;
            cur = cur->_right;
        }
        else if (cur->_key > key)
        {
            parent = cur;
            cur = cur->_left;
        }
        else
        {
           return false;
        }
    }
    cur = new Node(key);
    if (parent->_key < key)
    {
        parent->_right = cur;
    }
    else if (parent->_key > key)
    {
        parent->_left = cur;
    }
    return true;
}

插入具体过程细节处理:

  • 需要判断树是否为空树,如果为空,创建节点赋值给_root
  • 创建两个指针parent和cur保证节点的连接
  • 通过不同比较大小,直到cur找到为空的位置,创建节点
  • 该节点需要满足二叉搜索树的特性,需要再次判断,选择连接

2.5 二叉搜索树的删除(难点)

2.5.1 删除该子树根节点情况分析

首先查找元素是否在二叉搜索树中,如果不存在则返回false,否则要删除的节点可能分为下面三种情况。先到需要被删除的节点,这里就不重复实现了。

删除节点情况划分:

  1. 要删除的节点无孩子节点
  2. 要删除的节点只有一个孩子节点
  3. 要删除的节点有左、右孩子节点

2.5.2 删除第一、二情况节点

这里第一种和第一种情况可以归类为同一种情况。无论被删除节点是否有无真实存在的孩子节点,都可以看成要删除的节点只有一个孩子节点,将第一种情况看成第二种情况,被删除节点有空孩子节点。

if (cur->_left == nullptr)
{
    if (parent->_left == cur)
    {
        parent->_left = cur->_right;
    }
    else if (parent->_right == cur)
    {
        parent->_right = cur->_right;
    }
    delete cur;
}
else if (cur->_right == nullptr)
{
    if (parent->_left == cur)
    {
        parent->_right = cur->_left;
    }
    else if (parent->_right == cur)
    {
        parent->_left = cur->_left;
    }
    delete cur;
}

关于数据结构学习,我们需要借助具体的逻辑结构去实现"抽象"的物理结构。接下我也希望你们可以借助图和文字进行对代码的解读。

  1. 第一个判断分支决定,parent指向另外一个可能为空的节点。

  1. 第二个分支判断被删除节点相对parent节点的位置

判断结束后,parent节点进行连接操作进行删除操作。

  1. 小总结:判断被删除节点位置与被删除节点可能不为空孩子位置,进行连接即可。

草稿说明,上面是优化版本说明:

有了上面两个信息的话,比如通过parent->_left == cur需要被删除的节点是左节点,并且cur->_left == nullptr该节点左孩子节点为空,那么parent->_left = cur->_right;parent->_left 是根据第一个条件,该parent->_left需要重新连接新节点,那么新节点是谁?通过cur->_left == nullptr判断,该左孩子为空,肯定连接右孩子节点。


【高阶数据结构】深度探索二叉树进阶:二叉搜索树概念及其高效实现(二)https://developer.aliyun.com/article/1617405

相关文章
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
49 2
|
2月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
3月前
|
机器学习/深度学习 存储 算法
数据结构实验之二叉树实验基础
本实验旨在掌握二叉树的基本特性和遍历算法,包括先序、中序、后序的递归与非递归遍历方法。通过编程实践,加深对二叉树结构的理解,学习如何计算二叉树的深度、叶子节点数等属性。实验内容涉及创建二叉树、实现各种遍历算法及求解特定节点数量。
128 4
|
3月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
209 8
|
4月前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
3月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
328 9
|
3月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
53 1
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
142 77

热门文章

最新文章