目录

  • BST树概念
  • BST树操作
    • BST树的查找
    • BST树的插入
    • BST树的删除
  • 实现一个自己的BST树
    • BSTNode类和BSTree类
    • 查找操作;
    • 插入操作:
    • 删除操作:
  • 应用:
  • 二叉搜索树性能分析

对于普通的二叉树来说,能延伸出许多好用的数据结构,二叉搜索树(BST树)就是其中一个;

学习二叉搜索树,将为后续的AVL树与红黑树和map,set等STL容器打下坚实的基础;

BST树概念

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

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

BST树操作

BST树的查找

可以看到每步查找都能筛掉一般不符合的元素,有点类似于数组中的二分查找;

这也是二叉搜索树名字的由来,他的查找效率很高;

注意,不难发现,中序遍历BST树,就是一个升序的结构!;

BST树的插入

插入的具体过程如下:

按照二叉搜索树的性质,找到某个val合适的插入点;

BST树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回,

否则要删除的结点可能分下面四种情况

  1. 要删除的结点无孩子结点 -->直接删除
  2. 要删除的结点只有左孩子 -->左孩子直接与他的父亲连接(左or右),然后删掉它
  3. 要删除的结点只有右孩子 -->右孩子直接与他的父亲连接(左or右),然后删掉它
  4. 要删除的结点左右孩子都有;–>去它的右子树找最左节点,替换它的位置 用替代法删除结点!

实现一个自己的BST树

由于一般具有k-v结构的数据结构底层是BST树,那么我们这里也实现一个K-V结构的BST树;

  1. K模型:K模型即只有key作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值。 比如:给一个单词word,判断该单词是否拼写正确,具体方式如下:

以单词集合中的每个单词作为key,构建一棵二叉搜索树,

在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误

  1. KV模型:每一个关键码key,**都有与之对应的值Value,**即的键值对。该种方式在现实生 活中非常常见:

    比如英汉词典就是英文与中文的对应关系,通过英文可以快速找到与其对应的中文,英 文单词与其对应的中文就构成一种键值对;

    再比如统计单词次数,统计成功后,给定 单词就可快速找到其出现的次数,单词与其出现次数就是就构成一种键值对。

    <单词,中文含义>为键值对构造二叉搜索树,注意:二叉搜索树需要比较,键值对比较时只比较Key

    查询英文单词时,只需给出英文单词,就可快速找到与其对应的key

BSTNode类和BSTree类

基本框架:

template<class K,class V>
struct BSTNode {BSTNode(const K& key = K(), const V& value = V()): _pLeft(nullptr), _pRight(nullptr), _key(key), _Value(value){}BSTNode<T>* _pLeft;BSTNode<T>* _pRight;K _key;V _value
};
template<class K, class V>
class BSTree {typedef BSTNode<K, V> Node;
private:Node* _root;
}

查找操作;

 Node* Find(const K& key) {//根据BST树的特性来find;if (_root == nullptr) return nullptr;Node* cur = _root;//原则上来说 是没有重复key存在的while (cur) {if (key > cur->_key) {cur = cur->_pRight;}else if (key < cur->_key) {cur = cur->_pLeft;}else return cur;}return nullptr;}

插入操作:

 bool Insert(const K& key, const V& value){if (_root == nullptr) {_root = new Node({ key,value });return true;}Node* cur = _root;Node* prev = _root;//原则上来说 是没有重复key存在的while (cur) {if (key > cur->_key) {prev = cur;cur = cur->_pRight;}else if (key < cur->_key) {prev = cur;cur = cur->_pLeft;}else return false; //数据冗余,不插入;map,set的普通版本不允许key重复!}Node* newnode = new Node({ key,value });if (prev->_key < key) {prev->_pRight = newnode;}else {prev->_pLeft = newnode;}return true;}

删除操作:


bool Erase(const K& key)
{Node* cur = _root;Node* father = nullptr;while (cur) {if (key > cur->_key) {father = cur;cur = cur->_pRight;}else if (key < cur->_key) {father = cur;cur = cur->_pLeft;}else break;}if (!cur) return false;//处理下特殊情况:需要删root节点if (father == nullptr) {Node* tmp = _root;if (father->_pRight) {_root = father->_pRight;}else if (father->_pLeft) {_root = father->_pLeft;}delete tmp;return true;}//1,无孩子节点,直接删;if (!cur->_pLeft && !cur->_pRight) {if (father->_pLeft == cur){father->_pLeft = nullptr;}else father->_pRight = nullptr;}//2,有左孩子or右孩子;else if ((!cur->_pLeft && cur->_pRight) || (cur->_pLeft && !cur->_pRight)) {if (father->_pLeft == cur) {//cur是father的左  if (cur->_pLeft) father->_pLeft = cur->_pLeft;else father->_pLeft = cur->_pRight;}else {//cur是father的右if (cur->_pLeft) father->_pRight = cur->_pLeft;else  father->_pRight = cur->_pRight;}}else {//3.左右都有孩子;//替代法,找右子树最左节点替换他; 及的保存parent 替换的时候树得调整Node* p_replace = cur;Node* replace = cur->right;while (replace->_pLeft) {p_replace = replace;replace = replace->_pLeft;
;       }//swap(cur, rmin);//别乱用swap 会出错;if (father->_pLeft == cur) { //注意 这个father是cur的fatherfather->_pLeft = replace;}else {father->_pRight = replace;}cur->_val = replace->_val;//交换要删除节点的值与替代节点的值,之后把replace删了 删的时候替换的时候树得调整if (p_replace->_pLeft == replace) {p_replace->_pLeft = replace->_pLeft;}else {p_replace->_pRight = replace->_pRight;}cur = replace;//改变最后删的对象}delete cur;cur = nullptr;return true;
}

应用:

//统计词语出现的次数
string strs[] = { "苹果", "西瓜", "苹果", "樱桃", "苹果", "樱桃", "苹果", "樱桃", "苹果" };// 统计水果出现的次BSTree<string, int> countTree;for (auto str : strs){auto ret = countTree.Find(str);if (ret == NULL){countTree.Insert(str, 1);}else{ret->_value++;}}countTree.InOrder();

二叉搜索树性能分析

插入和删除操作都必须先查找,查找效率代表了二叉搜索树中各个操作的性能。

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的 深度的函数,即结点越深,则比较次数越多

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log2N

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:N/2

问题:如果退化成单支树,二叉搜索树的性能就失去了。那能否进行改进,不论按照什么次序插入关键码, 都可以是二叉搜索树的性能最佳?

AVL树!后面文章接着写

二叉搜索树详解--实现插入和删除相关推荐

  1. java二叉搜索树详解

    文章目录 一.概念 二.相关操作 2.0节点相关代码: 2.1查找 2.2插入 2.3删除(重难点) 2.4测试用例 三.小结 提示:以下是本篇文章正文内容,下面案例可供参考 一.概念 二叉搜索树又称 ...

  2. 二叉堆详解实现优先级队列

    二叉堆详解实现优先级队列 文章目录 二叉堆详解实现优先级队列 一.二叉堆概览 二.优先级队列概览 三.实现 swim 和 sink 四.实现 delMax 和 insert 五.最后总结 二叉堆(Bi ...

  3. 二叉树:二叉搜索树的创建和插入

    二叉搜索树又名二叉排序树. 大概简略的思维导图如下,方便记忆特性 基本二叉搜索树创建过程如下 /*数据结构如下*/ typedef struct tree {int data;struct tree ...

  4. 二叉搜索树的创建、插入、遍历、删除

    二叉搜索树 本文主要记录自己完成学校课程布置的有关"二叉搜索树"的代码闯关题的代码和思路心得,部分内容有借鉴身边大佬,借鉴部分会有标注. 二叉搜索树的结构体定义 struct no ...

  5. AVL树(二叉平衡树)详解与实现

    公众号文章链接 AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树 ...

  6. 第七章 二叉搜索树(b3)BST:删除

    转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/10247191.html

  7. C++初阶学习————二叉树进阶(二叉搜索树)

    二叉树进阶 二叉搜索树的概念 二叉搜索树的操作 基本框架 二叉搜索树的插入 二叉搜索树的查找 二叉搜索树的删除 整体代码 循环写法 递归写法 二叉搜索树的应用 二叉搜索树的性能分析 前面的文章介绍过二 ...

  8. C++ 第八节数据结构 第七节 ——二叉搜索树 AVL树 红黑树(底层原理图+模拟实现)

    第一次,C++和数据结构联合推出,倾情献上呦~~ 给个关注吧 23333~~~~~~(现在每天系统就给我一个机器人的粉丝量了55555~~~~~) 本节内容,我们将着重来探讨 二叉树 中特殊的两种树- ...

  9. 二叉树进阶--二叉搜索树

    目录 1.二叉搜索树 1.1 二叉搜索树概念 1.2 二叉搜索树操作 1.3 二叉搜索树的实现 1.4 二叉搜索树的应用 1.5 二叉搜索树的性能分析 2.二叉树进阶经典题: 1.二叉搜索树 1.1 ...

最新文章

  1. Luogu P1087 FBI树
  2. 参加51CTO学院软考培训,通过后感想
  3. 批量处理Excel文件的模块----xlwings
  4. kafka启动异常:kafka.common.InconsistentClusterIdException: The Cluster ID xxx
  5. 判断指定目录下的所有[图片]的扩展名, 并打印出文件名.
  6. 设计模式之静态代理模式实战
  7. java流与文件——内存映射文件
  8. Camel 2.11 –没有Spring的Camel Web应用程序
  9. java字节流分为_Java文件流可分为字节流和字符流。
  10. 微软开源InnerEye:让医学影像AI普及化
  11. ZOJ-1010 奇偶剪枝
  12. 干货 | 我如何考察面试者的机器学习水平
  13. 看了某LINUX打包规范,没搞明白怎么支持多CPU,自己测试过没有?
  14. android HandlerThread源码解析
  15. 数字孪生网络(DTN)架构
  16. 计算机桌面下方任务栏图标不见了,任务栏显示桌面图标不见怎么办
  17. 重启MySQL报Unit mysqld.service could not be
  18. 安装爱剪辑计算机丢失,爱剪辑没保存的视频怎么恢复?
  19. Linux系统Docker配置阿里云镜像加速器
  20. 【Tensorflow教程笔记】深度强化学习(DRL)

热门文章

  1. 快速实现抖音分享与第三方登录
  2. 人工智能领域最佳5种编程语言
  3. ORACLE数据库NLS_CHARACTERSET和NLS_NCHAR_CHARACTERSET区别
  4. 华为OD开发岗面试记录
  5. 影碟出租管理c语言程序,影碟出租管理系统
  6. uniapp的打包:h5、微信小程序以及APP方式
  7. PXIe高速数据采集板卡的技术参数
  8. 爆款!如何利用知乎引上万流量,我是这样做的!|实战
  9. 小米日历和WIN10自带日历的日程同步
  10. HTML五子棋游戏论文,五子棋毕业论文-HTML开发五子棋的原型设计.doc