当前位置: 首页 > news >正文

二叉搜索树,咕咕咕

1.概念

二叉搜索树又叫二叉排序树,或者是一棵空树,也可以是有以下性质的二叉树:

左子树不为空,左子树上所有的点值都小于等于根结点的值。

右子树不为空,右子树上所有的点值都大于等于根结点的值。

它的左右子树也都是二叉搜索树。

二叉搜索树中可以支持插入相同的值,也可以不支持相等的值,map/set/multimap/multiset系列底层容器就是二叉搜索树,map/set不支持插入相等的值,multimap/multiset支持插入相等的值。

2.性能分析

最优情况下:二叉搜索树为完全二叉树,高度log 2 N

最差情况下:退化为单支树,高度为N

综合而言二叉搜索树的增删查改的时间复杂度为O(N),它可以进化成平衡二叉树和红黑树才能适用于在内存中存储和搜索数据

二分查找也可以实现log 2 N 的查找效率,但是有2个缺点:

需要存储在支持下标随机访问的结构中,并且有序。

插入和删除数据效率低,因为存储在下标随机访问的结构中,插入和删除数据一般需要挪动数据。

3.插入

1.树为空,直接新增结点,赋值给root指针

2.树不空,按二叉搜索树,插入值比当前结点大,向右走,插入值比当前结点小,往左走,找到空位置,插入。

3.如果支持插入相同的值,插入值和当前结点相等的值可以往右走,也可以往左走,找到空位置,插入新结点(不要一会向右,一会向左)

4.查找

1.从根开始比较,查找x,x比根值大,向右走,x比根值小,向左走

2.最多查找高度次数,走到空,没找到,就不存在

3.如果不支持插入相等的值,找到x就返回

4.如果支持插入相等的值,意味着有多个x存在,一般要求查找中序的第一个x

5.删除

查找元素是否在二叉搜索树中,不存在的话,返回false

如果存在:

1.删除结点N左右子树都是空(N结点的父结点对应的孩子指针置空,直接删除N结点)

2.删除结点N左子树为空(把N结点的父结点对应的孩子指针指向N的右孩子,直接删除N结点)

3.删除结点N右子树为空(把N结点的父结点对应的孩子指针指向N的左孩子,直接删除N结点)

4。删除结点N左右子树不为空(无法直接删除N结点,找N结点左子树值最大结点R(左子树中最右的)或者右子树值最小的结点(右子树最左的结点)代替N,因为这2个结点中任意一个放到N的位置都满足二叉搜索树的规则,把该结点与N的值交换,转变为删除R结点位置可以直接删除

6.实现的代码

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;
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{
parent->left=cur;
}
return true;
}bool Find(const K& key)
{
Node* cur=root;
while(cur)
{
if(cur->key<key)
{
cur=cur->right;
}
else if(cur->key<key)
{
cur=cur->left;
}
else{
return true;
}
}
return false;
}bool Erase(const K& key)
{
Node* parent=nullptr;
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{
if(cur->left==nullptr)
{
if(parent==nullptr)
{
root=cur->right;
}
else{
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{
Node* rightminp=cur;
Node* rightmin=cur->right;
while(rightmin->left)
{
rightminp=rightmin;
rightmin=rightmin->left;
}
cur->key=rightmin->key;
if(rightminp->left==rightmin)
rightminp->left=rightmin->right;
else
rightminp->right=rightmin->right;
delete rightmin;
return true;
}
}
}
return false;
}void InOrder()
{
_InOrder(root);
cout<<endl;
}
private:
void _InOrder(Node* root)
{
if(root==nullptr)
{
return;
}
_InOrder(root->left);
cout<<root->key<<" ";
_InOrder(root->right);
}
private:
Node* root=nullptr;
};

7.二叉搜索树key/value

key搜索场景:只有key作为关键码,结构中只要存储key就行,关键码即为需要搜索到的值,搜索场景只要判断key在不在,key搜索场景实现的二叉搜索树可以增删查,不能改

key/value搜索场景:每一个关键码key都有与之对应的值value,value可以是任意类型对象,树的结构中除了存储key还要存储对应的value,key/value搜索场景实现的二叉搜索树不支持修改key但是可以修改value

template<class K,class V>
struct BSTNode
{
K key;
V value;
BSTNode<K,V>* left;
BSTNode<K,V>* right;
BSTNode(const K& key,const V& value):key(key),value(value),
left(nullptr),right(nullptr)
{
}
};
template<class K,class V>
class BSTree
{
typedef BSTNode<K,V> Node;
public:
BSTree()=default;//让系统生成默认构造
BSTree(const BSTree<K,V>& t)
{
root=Copy(t.root);
}
BSTree<K,V>& operator=(BSTree<K,V> t)
{
swap(root,t.root);
return *this;
}
~BSTree()
{
Destroy(root);
root=nullptr;
}
bool Insert(const K& key,const V& value)
{
if(root==nullptr)
{
root=new Node(key,value);
return true;
}
Node* parent=nullptr;
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,value);
if(parent->key<key)
{
parent->right=cur;
}
else{
parent->left=cur;
}
return true;
}Node* Find(const K& key)
{
Node* cur=root;
while(cur)
{
if(cur->key<key)
{
cur=cur->right;
}
else if(cur->key>key)
{
cur=cur->left;
}
else{
return cur;
}
}
return nullptr;
}bool Erase(const K& key)
{
Node* parent=nullptr;
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{
if(cur->left==nullptr)
{
if(parent==nullptr)
{
root=cur->right;
}
else{
if(parent->left==cur)
parent->left=cur->left;
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{
Node* rightminp=cur;
Node* rightmin=cur->right;
while(rightmin->left)
{
rightminp=rightmin;
rightmin=rightmin->left;
}
cur->key=rightmin->key;
if(rightminp->left==rightmin)
rightminp->left=rightmin->right;
else
rightminp->right=rightmin->right;
delete rightmin;
return true;
}
}
}
return false;
}void InOrder()
{
_InOrder(root);
cout<<endl;
}
private:
void _InOrder(Node* root)
{
if(root==nullptr)
{
return;
}
_InOrder(root->left);
cout<<root->key<<";"<<root->value<<endl;
_InOrder(root->right);
}
void Destroy(Node* root){
if(root==nullptr)
return;
Destroy(root->left);
Destroy(root->right);
delete root;
}
Node* Copy(Node* root)
{
if(root==nullptr)
return nullptr;
Node* newroot=new Node(root->key,root->value);
newroot->left=Copy(root->left);
newroot->right=Copy(root->right);
return newroot;
}
private:
Node* root=nullptr;
};

http://www.dtcms.com/a/539970.html

相关文章:

  • 可用 Docker (DockerHub) 国内镜像源加速列表 - 长期维护(截至 2025 年 06 月 15 日)
  • QtQuick3D入门(5):实例化渲染
  • 浙人医基于金仓 KFS 工具信创落地:多数据库协同难题解决方案详讲
  • [C++STL] :list的简介和使用
  • Nacos配置中心实战进阶:多场景动态刷新全解析
  • Linux写sh开机启动脚本-bash报错的两种解决方法
  • 注册协议通知
  • wordpress网站部署百度一下一下你就知道
  • 健康濮阳门户网站建设装企erp管理系统
  • C++ stack和queue之OJ题目
  • 【网络】在windows下,使用自带的ftp服务器,并添加账户
  • 基于python大数据的网络新闻可视化及分析系统
  • 6.1.1.3 大数据方法论与实践指南-SparkStreaming 任务优化实践
  • uniapp实现PDF的预览
  • 推送远程git仓库报错:内部服务错误
  • Qt 6以上版本都试用 连接 MySQL 数据库全流程(CMake 环境)
  • 使用 C# 打印 PDF 文档:基于 Spire.PDF 的实战教程
  • 数据库--JDBC编程
  • 开源一个基于OpenCV的模糊检测工具,支持局部分析和视频处理
  • 政协网站建设情况汇报为什么wordpress安装成了英文版
  • 不做网站只做推广可以么襄阳网站建设首选公司哪家好
  • 10月28日
  • 【加精】C# XML差异对比 (直接用)
  • JavaScript eval函数
  • C++笔记(面向对象)对象和对象之间关系
  • 注册中心 eureka、nacos、consul、zookeeper、redis对比
  • c# 基于xml文件和devexpress插件 的工作流程配置
  • 【四川政务服务网-注册安全分析报告】
  • 基于海思AI ISP视频编解码IPC平台的算法承载方案
  • C语言入门(十二):函数的递归