数据结构之二叉搜索树(Binary Search Tree)

devtools/2024/12/21 21:29:12/

数据结构之二叉搜索树(Binary Search Tree)

  • 1. ⼆叉搜索树的概念
  • 2. ⼆叉搜索树的性能分析
  • 3.⼆叉搜索树的 查,删,插(没有改,因为没有意义会破坏本质)(源码)

1. ⼆叉搜索树的概念

⼆叉搜索树⼜称⼆叉排序树,它或者是⼀棵空树,或者是具有以下性质的⼆叉树:
• 若它的左⼦树不为空,则左⼦树上所有结点的值都⼩于等于根结点的值
• 若它的右⼦树不为空,则右⼦树上所有结点的值都⼤于等于根结点的值
• 它的左右⼦树也分别为⼆叉搜索树

2. ⼆叉搜索树的性能分析

最优情况下,⼆叉搜索树为完全⼆叉树(或者接近完全⼆叉树),其⾼度为: O(log2 N)
最差情况下,⼆叉搜索树退化为单⽀树(或者类似单⽀),其⾼度为: O( n/2)
所以综合⽽⾔⼆叉搜索树增删查改时间复杂度为: O(N)

在这里插入图片描述

那么这样的效率显然是⽆法满⾜我们需求的,我们后续课程需要继续讲解⼆叉搜索树的变形,平衡⼆叉搜索树AVL树和红⿊树,才能适⽤于我们在内存中存储和搜索数据。另外需要说明的是,⼆分查找也可以实现 O(logN) 级别的查找效率,但是⼆分查找有两⼤缺陷:
1. 需要存储在⽀持下标随机访问的结构中,并且有序。
2. 插⼊和删除数据效率很低,因为存储在下标随机访问的结构中,插⼊和删除数据⼀般需要挪动数据。
这⾥也就体现出了平衡⼆叉搜索树的价值。

3.⼆叉搜索树的 查,删,插(没有改,因为没有意义会破坏本质)(源码)

#pragma once
#include <iostream>
using namespace std;
//bst时间复杂度:最差情况下 :会退化成链表形状 O(N)
//理想状态下:O(logn)
template <class k>
struct bstnode {k _key;bstnode<k>* _left;bstnode<k>* _right;bstnode(const k& key):_key(key), _left(nullptr), _right(nullptr){};
};
template<class k>
class bstree {typedef bstnode<k> node;
public:bool insert(const k& key)//插入-(不支持相等值插入,要想实现,"改"下面判断条件){//先处理空树if (_root == nullptr){_root = new node(key);return true;}node* parent = nullptr;//作用:为了最后连接插入节点node* cur = _root;//把root赋给cur,让key从根节点开始找while (cur){if (cur->_key > key)//往左走{parent = cur;cur = parent->_left;}else if (cur->_key < key)//往右走{parent = cur;cur = parent->_right;}else //相等{return false;}}//循环走完,cur来到空节点//开始插入cur = new node(key);//走到这里不知道key比当前的parent大还是小,所以进行比较if (key > parent->_key)//去右{parent->_right = cur;}else//这里包含 小于 和 等于 两种情况{parent->_left = cur;}}bool find(const k& key)//查找{//查找逻辑较简单:从根节点开始找,找到空就是不存在//找的次数:最多"树的高度"次cout << "你要查找的值 :" << key << endl;cout << "存在(1)|不存在(0): ";node* cur = _root;while (cur){if (cur->_key > key){cur = cur->_left;}else if (cur->_key < key){cur = cur->_right;}else{return true;}}return false;}void inorder(){cout << "中序遍历(递归法): ";_inorder(_root);cout << endl;}//删除,分为四种情况(假设要删除的节点是 n)//1.n的左右孩子都为空--可以归为2,3情况来处理//2.n的左孩子为空--让n的父亲节点指向n的右孩子,直接delete n//3.n的右孩子为空--让n的父亲节点指向n的左孩子,直接delete n//4.n的左右孩子都不为空--只能用 替换法,找n左子树的最大节点(最右节点)//,或者找n的右子树的最小节点(最左节点),和n进行替换,然后delete n//删除的逻辑和查找差不多,都是先找到节点,没找到返回空bool erase(const k& key){node* parent = nullptr;//作用:为了最后连接插入节点node* cur = _root;//把root赋给cur,让key从根节点开始找while (cur){if (cur->_key > key)//往左走{parent = cur;cur = parent->_left;}else if (cur->_key < key)//往右走{parent = cur;cur = parent->_right;}else //相等,开始删除{				if (cur->_left == nullptr)//只有一个孩子或者没有孩子的情况{//这里有个小坑:就是要删除的节点是根节点就会崩,所以得提前判断一下if (parent == nullptr)//要删除根节点的情况,直接改根{_root = cur->_right;}else{//这里不知道cur是parent的左还是右有两种情况会导致结果有偏差,所以要判断一下if (parent->_left == cur) parent->_left = cur->_right;else parent->_right = cur->_right;}delete cur;return true;}else if (cur->_right == nullptr){if (parent == nullptr){_root = cur->_left;}else{if (parent->_left == cur) parent->_left = cur->_left;else parent->_right = cur->_left;}delete cur;return true;}else//有两个孩子的情况{//这里我用的代替节点是n右子树的最左节点node* replaceparent = cur;node* replace = cur->_right;while (replace->_left){replaceparent = replace;replace = replace->_left;						}//这里找到了代替节点,开始替换cur->_key = replace->_key;//这里的情况和上面一样不知道是父亲节点的 左 还是右if (replaceparent->_left == replace) replaceparent->_left = replace->_right;else replaceparent->_right = replace->_right;delete replace;return true;}}}//没找到return false;}
private:void _inorder(node* root)//中序递归{if (root==nullptr){return;}_inorder(root->_left);cout << root->_key << " ";_inorder(root->_right);}
private:node* _root = nullptr;
};
#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include"bst.h"
using namespace std;int main()
{int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };bstree<int> t;for (auto e : a){t.insert(e);}t.inorder();//cout<<t.find(3)<<endl;////cout<<t.find(122);for (auto e : a){t.erase(e);t.inorder();}return 0;
}

http://www.ppmy.cn/devtools/144184.html

相关文章

C语言双向链表

1.思维导图 2.单向循环链表的所有操作 创建 loopLinkPtr create() {loopLinkPtr H(loopLinkPtr)malloc(sizeof(loopLink));if (NULLH){printf("创建失败\n");return NULL;}H->len 0;H->next H;printf("创建成功\n");return H; }输出结果&#xf…

OpenCV及基本用法

一.OpenCV介绍 1.OpenCV 的全称是 Open Source Computer Vision Library&#xff0c;是一个开放源代码的 计算机视觉库。OpenCV 是最初由英特尔公司发起并开发&#xff0c;以 BSD 许可证授权发 行&#xff0c;可以在商业和研究领域中免费使用&#xff0c;现在美国 Willow Gar…

挑战一个月基本掌握C++(第七天)了解指针,引用,时间,输入输出,结构体,vector容器,数据结构 - 通用完结

一 指针 每一个变量都有一个内存位置&#xff0c;每一个内存位置都定义了可使用连字号&#xff08;&&#xff09;运算符访问的地址&#xff0c;它表示了在内存中的一个地址。 下面的实例&#xff0c;它将输出定义的变量地址&#xff1a; #include <iostream>using…

uniapp中的uni-file-picker组件上传多张图片到服务器

由于在uniapp官方文档中的uni-file-picker组件可实现图片上传功能&#xff0c;默认的是上传到自带的服务&#xff0c;所以我们要修改成自己的服务器 1. 添加 :auto-upload"false" 加上这个取消自动上传 <uni-file-picker v-model"jobAddUpdateForm.imag…

我应该如何安装Python3

安装Python3的步骤会因操作系统的不同而有所差异。以下是在不同操作系统上安装Python3的详细步骤&#xff1a; 一、在Windows系统上安装Python3 下载Python安装包&#xff1a; 打开任意浏览器&#xff0c;访问Python官方网站&#xff08;https://www.python.org&#xff09;。…

深度学习模型中增加随机性可以通过多种方式实现,以下是一些可以应用到你的 `TCNAttentionLSTM`

在深度学习模型中增加随机性可以通过多种方式实现&#xff0c;以下是一些可以应用到你的TCNAttentionLSTM模型中的方法&#xff1a; ### 1. Dropout 你已经在模型中使用了dropout&#xff0c;这是增加随机性的一种常见方法。你可以通过调整dropout率来控制随机性的程度。 ###…

Python球球大作战

系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…

stm32进硬件错误怎么回事

STM32进入硬件错误状态&#xff0c;通常是由一些特定的编程或硬件问题引起的。以下是一些可能的原因及相应的解决方法&#xff1a; 可能的原因 数组越界操作&#xff1a;在编程过程中&#xff0c;如果数组访问超出了其定义的边界&#xff0c;可能会导致内存访问错误&#xff0…