【C++研发面试笔记】9. 基本数据结构-二叉查找树BST

本文详细介绍了二叉查找树(BST)的基本概念、搜索、建立、插入与删除操作,并探讨了平衡问题对性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【C++研发面试笔记】9. 基本数据结构-二叉查找树BST

BST树即二叉搜索树,其满足如下条件:
1.所有非叶子结点至多拥有两个儿子(Left和Right);
2.所有结点存储一个关键字;
3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;

9.1 BST树的搜索

  • 从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;
  • 否则如果查询关键字比结点关键字小,就进入左儿子;
  • 如果比结点关键字大,就进入右儿子;
  • 如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;

如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变BST树结构(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销;
同样的关键字集合有可能导致不同的树结构索引;所以,使用BST树还要考虑尽可能让BST树保持左图的结构,和避免右图的结构,也就是所谓的“平衡”问题;


9.2 BST的建立

9.2.1 结构

这里写图片描述

9.2.2 插入

这里写图片描述
递归方法:
这里写图片描述

9.2.3 构建

这里写图片描述

9.2.4 查找

这里写图片描述
递归方法:
这里写图片描述
先序遍历
这里写图片描述
中序遍历
这里写图片描述

9.2.5 删除节点

删除操作也类似于查找,是个递归过程,只不过删除操作在找到被删除节点后的处理要复杂些,需考虑下面4种情形:

  1. 当前节点的关键值等于待删除关键值,则进入删除处理过程;
  2. 当前节点的关键值小于待插入节点关键值,根据BST的定义,应在当前节点的左子树上递归删除操作;
  3. 当前节点的关键值大于待插入节点关键值,根据BST的定义,应在当前节点的右子树上递归删除操作;
  4. 若当前节点为空,则说明查找不到待删除关键值的节点,返回-1指示删除失败。

删除处理过程又需要考虑以前几种情形:

  1. 待删除节点为叶子节点(左右孩子均为空);
    a) 将待删除节点的父节点指向该待删除节点的指针置为空,
    b) 删除待删除节点。
  2. 待删除节点的左孩子为空,右孩子非空;
    a) 将待删除节点的父节点重新指向待删除节点的右孩子
    b) 删除待删除节点。
  3. 待删除节点的左孩子非空,右孩子为空;
    a) 将待删除节点的父节点重新指向待删除节点的左孩子
    b) 删除待删除节点
  4. 待删除节点的左孩子非空,右孩子非空。
    a) 将待删除节点的关键值与其右子树上值最小节点的值交换
    b) 也可以选择待删除节点左子树上的最大值节点进行交换

这篇博文是个人的学习笔记,内容许多来源于网络(包括优快云、博客园及百度百科等),博主主要做了微不足道的整理工作。由于在做笔记的时候没有注明来源,所以如果有作者看到上述文字中有自己的原创内容,请私信本人修改或注明来源,非常感谢>_<

### 二叉查找树数据结构中的应用 二叉查找树(Binary Search Tree, BST)是一种重要的数据结构,其节点的值具有特定的顺序关系。对于每个节点,其左子中所有节点的值均小于该节点的值,而右子中所有节点的值均大于该节点的值[^1]。这种性质使得二叉查找树在插入、删除和查询操作上表现优异,尤其在动态数据集合中能够提供高效的性能。 #### 1. 插入操作 在二叉查找树中,插入新节点的过程是递归进行的。如果当前为空,则直接创建一个新节点作为根节点;否则,根据新节点的值与当前节点的值比较,决定向左子还是右子继续插入。以下是插入操作的代码示例: ```c BiTreeNode* insertBiSortTree(BiTreeNode* root, int key) { if (!root) { root = (BiTreeNode*)malloc(sizeof(BiTreeNode)); root->data = key; root->left = NULL; root->right = NULL; } else { if (key > root->data) root->right = insertBiSortTree(root->right, key); else if (key < root->data) root->left = insertBiSortTree(root->left, key); } return root; } ``` 此代码片段展示了如何递归地将新节点插入到二叉查找树中[^2]。 #### 2. 创建二叉查找树 通过遍历一个无序数组并依次调用插入函数,可以构建一棵二叉查找树。以下代码展示了如何从数组中创建二叉查找树: ```c BiTreeNode* creatBiSortTree(int* arr, int n) { BiTreeNode* root = NULL; for (int i = 0; i < n; i++) { root = insertBiSortTree(root, arr[i]); } return root; } ``` 这段代码通过循环调用 `insertBiSortTree` 函数,逐步构建出完整的二叉查找树。 #### 3. 中序遍历 中序遍历是一种常见的遍历方式,特别适用于二叉查找树。由于二叉查找树的性质,中序遍历的结果是一个升序排列的序列。以下是实现中序遍历的代码: ```c int* InOrder(BiTreeNode* root, int* arr, int &i) { if (!root) return NULL; InOrder(root->left, arr, i); arr[i++] = root->data; InOrder(root->right, arr, i); return arr; } ``` 此代码实现了对二叉查找树的中序遍历,并将结果存储到数组中[^3]。 #### 4. 判断数列是否升序 在某些场景下,需要验证中序遍历后的数列是否为升序。以下代码展示了如何判断一个数列是否为升序: ```c bool isOrder(int* arr, int n) { for (int j = 0; j < n - 1; j++) { if (arr[j + 1] < arr[j]) return false; } return true; } ``` 此函数通过遍历数组,逐一比较相邻元素来判断数列是否满足升序条件。 ### 总结 二叉查找树作为一种高效的数据结构,在动态数据集合的操作中表现出色。它支持快速的插入、删除和查询操作,并且通过中序遍历可以轻松获得有序序列。这些特性使其成为许多实际应用场景中的首选数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值