欢迎来到本期节目- - -
二叉搜索树(去重版)
二叉搜索树的概念
定义:
对于该树的任意非空节点的值,左子树上所有节点的值小于等于给该节点,右子树所有节点的值大于等于该节点; |
任意节点的左右子树都为二叉搜索树; |
二叉搜索树不支持修改key值,否则会破会搜索树结构;
性能:
需要从两种极端情况综合来看;
理想情况:
一颗二叉搜索树的最佳情况是一颗完全二叉树或者接近完全二叉树;此时,高度为logN
二叉搜索树的插入、删除、查找效率为Ο(logN)最差情况:
此时退化成了单支树,高度为N
二叉搜索树的插入、删除、查找效率为Ο(N)
在实际运用中,很少机率是最佳情况,所以综合来看,二叉搜索树的增、删、查的效率是O(N).
二叉搜索树的插入
逻辑过程:
向一颗二叉搜索树tree插入一个节点Node;
如果tree是空树,则Node为根,插入成功;
如果tree是非空树,那么需要知道在哪插入;
- 可以给两个指针cur和parent,cur从tree的根开始,parent记录cur的父亲节点;
- 如果cur的key值小于Node的key值,让cur往右子树走;
- 如果cur的key值大于Node的key值,让cur往左子树走;
- 如果等于,插入失败;
- 直到cur走到空为止,然后parent连接Node节点,插入成功;
动图演示:
代码实操:
public:
bool Insert(const K& key,const V& val)
{
BSTNode* node = new BSTNode(key, val);
if (_root == nullptr)
{
_root = node;
return true;
}
else
{
BSTNode* cur = _root;
BSTNode* parent = nullptr;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
if (key > parent->_key)
{
parent->_right = node;
}
else
{
parent->_left = node;
}
return true;
}
}
二叉搜索树的删除
逻辑过程:
在一颗二叉搜索树tree中删除一个节点Node;
如果tree为空树,删除失败;
如果tree为非空树,依据key寻找对应删除节点;
用cur记录当前节点,parent记录cur的父亲;
如果没找到,删除失败;
如果找到了:
1.目标节点cur的左右子树都为空;
那么直接删除cur,让parent指向nullptr;2.目标节点cur只有一个左子树;
该节点cur的右子树为空,左子树不为空,依据搜索树规则有:
cur如果在parent的左子树,说明cur的左子树也在parent左边,则cur的左子树小于parent,让cur的左子树做parent的左子树;
cur如果在parent的右子树,说明cur的左子树也在parent右边,则cur的左子树大于parent,让cur的左子树做parent的右子树;3.目标节点cur只有一个右子树;
和上一情况类似;4.目标节点cur左右子树都不为空;
该节点cur的左右子树均不为空,则需要使用替换法;
将cur的左子树的最右节点或者右子树的最左节点替换cur;
这样既保持了二叉搜索树结构,也把删除问题转换为了上述情况,因为最左节点的左子树一定为空;最右节点的右子树一定为空;
总的来说,可以把1,2,3情况归为一类,将4转换为上述的一类情况;
动图演示:
代码实操:
public:
bool Erase(const K& key)
{
BSTNode* parent = nullptr;
BSTNode* cur = _root;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
if (cur->_left == nullptr)
{
if (cur == _root)
{
_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 (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
return true;
}
BSTNode* replacement = cur;
BSTNode* replaceparent = cur->_right;
while (replacement->_left)
{
replaceparent = replacement;
replacement = replacement->_left;
}
cur->_key = replacement->_key;
cur->_val = replacement->_val;
if (replaceparent->_left == replacement)
{
replaceparent->_left = replacement->_right;
}
else
{
replaceparent->_right = replacement->_right;
}
delete replacement;
return true;
}
}
return false;
}
二叉搜索树的查找
逻辑过程:
在一颗二叉搜索树tree中查找一个节点Node;
如果tree为空,则查找失败;
如果tree为非空;
- 给cur记录当前节点,parent记录cur的父亲节点;
- 如果cur的key值小于Node的key值,让cur往右子树走;
- 如果cur的key值大于Node的key值,让cur往左子树走;
- 如果等于,查找成功;
- 如果cur走到空节点,查找失败;
查找和插入类似,所以不做动图演示了;
代码实操:
public:
BSTNode* Find(const K& key)
{
BSTNode* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
二叉搜索树的遍历
逻辑过程:
二叉搜索树最明显的特征就是中序遍历的结果是递增;
遇到根先打印左子树,然后再打印根,然后再打印右子树;
动图演示:
private:
void _Inorder(BSTNode* _root)
{
if (_root)
{
_Inorder(_root->_left);
cout << _root->_key << ":" << _root->_val << endl;
_Inorder(_root->_right);
}
}
二叉搜索树的实现
#pragma once
#include<iostream>
#include<string>
using namespace std;
template<class K, class V>
class BSTNode
{
public:
K _key;
V _val;
BSTNode<K, V>* _left;
BSTNode<K, V>* _right;
BSTNode(const K& key = K(), const V& val = V())
{
_key = key;
_val = val;
_left = _right = nullptr;
}
};
template<class K,class V>
class BSTree
{
typedef BSTNode<K, V> BSTNode;
public:
BSTree() = default;
BSTree(const BSTree& tree)
{
_root = copy(tree._root);
}
BSTree& operator=(BSTree tree)
{
std::swap(_root, tree._root);
return *this;
}
bool Insert(const K& key,const V& val)
{
BSTNode* node = new BSTNode(key, val);
if (_root == nullptr)
{
_root = node;
return true;
}
else
{
BSTNode* cur = _root;
BSTNode* parent = nullptr;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
if (key > parent->_key)
{
parent->_right = node;
}
else
{
parent->_left = node;
}
return true;
}
}
bool Erase(const K& key)
{
BSTNode* parent = nullptr;
BSTNode* cur = _root;
while (cur)
{
if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else
{
if (cur->_left == nullptr)
{
if (cur == _root)
{
_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 (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
return true;
}
BSTNode* replacement = cur;
BSTNode* replaceparent = cur->_right;
while (replacement->_left)
{
replaceparent = replacement;
replacement = replacement->_left;
}
cur->_key = replacement->_key;
cur->_val = replacement->_val;
if (replaceparent->_left == replacement)
{
replaceparent->_left = replacement->_right;
}
else
{
replaceparent->_right = replacement->_right;
}
delete replacement;
return true;
}
}
return false;
}
BSTNode* Find(const K& key)
{
BSTNode* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->_right;
}
else if (key < cur->_key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
void Inorder()
{
_Inorder(_root);
}
~BSTree()
{
_destory(_root);
_root = nullptr;
}
private:
BSTNode* _root = nullptr;
void _Inorder(BSTNode* _root)
{
if (_root)
{
_Inorder(_root->_left);
cout << _root->_key << ":" << _root->_val << endl;
_Inorder(_root->_right);
}
}
void _destory(BSTNode* _root)
{
if (_root)
{
_destory(_root->_left);
_destory(_root->_right);
delete _root;
}
}
BSTNode* copy(BSTNode* _root)
{
if (_root == nullptr)
return nullptr;
BSTNode* newroot = new BSTNode(_root->_key, _root->_val);
newroot->_left = copy(_root->_left);
newroot->_right = copy(_root->_right);
return newroot;
}
};
希望本片文章对您有帮助,请点赞支持一下吧😘💕