高阶数据结构 | 二叉搜索树(Binary Search Tree)
Posted _BitterSweet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高阶数据结构 | 二叉搜索树(Binary Search Tree)相关的知识,希望对你有一定的参考价值。
二叉搜索树(Binary Search Tree)
1.二叉搜索树的概念
二叉搜索树又叫二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树
- 总结就是只要符合根节点大于一边,小于一边即可
2.二叉搜索树的特性
- 二叉搜索树的中序遍历一定是有序的
3.二叉搜索树的简单实现
3.1二叉搜索树的查找
- 从根节点出发,如果大于根节点,则查找右子树,小于根节点,则查找左子树,如果遍历完还没有找到,则返回空
//查找
Node* find(const T& val)
{
//从根节点开始查找
Node* cur = _root;
while (cur)
{
if (cur->_val == val)
return cur;
else if (cur->_val < val)
cur = cur->_right;
else
cur = cur->_left;
}
//不存在返回空
return nullptr;
}
3.2二叉搜索树的插入
-
插入分两种情况,第一种是如果为空树,就直接插入
-
第二种,如果不是空树,则需要先搜索,再插入,并且判断数据是否存在
//插入:1.空树(直接插入) 2.非空树(搜索+插入)还要判断数据是否存在
bool insert(const T& val)
{
//判断是否为空树
if (_root == nullptr)
{
_root = new Node(val);
return true;
}
//搜索插入的位置
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (cur->_val == val)
return false;
else if (cur->_val < val)
cur = cur->_left;
else
cur = cur->_right;
}
//确定新插入数据的左右位置
cur = new Node(val);
if (parent->_val < val)
parent->_right = cur;
else
parent->_left = cur;
return true;
}
3.3二叉搜索树的删除
- 首先需要查找元素是否在树中,如果不存在直接返回
- 如果元素存在,则一共存在以下几种情况:
- 第一种:叶子节点(删除1,4,9)
- 第二种:删除的节点只有一个子树(删除 7),让需要被删除的节点的父亲直接指向子树
- 第三种:待删除的节点左右子树均有
//删除
bool erase(const T& val)
{
//1.判断根节点
if (_root == nullptr)
return false;
Node* cur = _root;
Node* parent = nullptr;
//查找
while (cur)
{
if (cur->_val == val)
break;
else if (cur->_val < val)
{
parent = cur;//更新节点
cur = cur->_right;
}
else
{
parent = cur;
cur = cur->_left;
}
}
//判断cur是否为空
if (cur == nullptr)
return false;
//删除:叶子or非叶子?
//1.叶子节点
if (cur->_left == nullptr && cur->_right == nullptr)
{
//判断删除的是否为根节点
if (cur == _root)
{
_root = nullptr;
}
else
{
if (parent->_left == cur)
parent->_left == nullptr;
else
parent->_right == nullptr;
}
delete cur;
}
//2.非叶子节点
//左边为空,右边不为空
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;
}
//左边不为空,右边为空
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;
}
//左右都不为空
else
{
//左右孩子都存在
//1.找左子树最右节点
Node* child = cur->_left;
parent = cur;
while (child->_right)
{
parent = child;
child = child->_right;
}
//2.最右节点的值覆盖cur位置的值
cur->_val = child->_val;
//3.重新链接
if (parent->_left == child)
parent->_left = child->_left;
else
parent->_right = child->_left;
//4.删除最右节点
delete child;
}
return true;
}
3.4实现的源代码整合
#include<iostream>
using namespace std;
template<class T>
struct Node
{
T _val;
Node* _left;
Node* _right;
Node(const T& val = T())
:_val(val)
,_left(nullptr)
,_right(nullptr)
{}
};
template<class T>
class BST
{
public:
typedef Node<T> Node;
BST()//构造
:_root(nullptr)
{}
BST(const BST<T>& val)//拷贝构造---深拷贝
{
//结构也要拷过来,走到什么位置,就把对应的节点创建出来
_root = copy(bst._root);
}
//递归拷贝节点
Node* copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* cur = new(root->_val);
cur->_left = copy(root->_left);
cur->_right = copy(root->_right);
return cur;
}
~BST()
{
if (_root)
destroy(_root);
}
//销毁
void destroy(Node* root)
{
if (root)
{
destroy(root->_left);
destroy(root->_right);
delete root;
root = nullptr;
}
}
//查找
Node* find(const T& val)
{
//从根节点开始查找
Node* cur = _root;
while (cur)
{
if (cur->_val == val)
return cur;
else if (cur->_val < val)
cur = cur->_right;
else
cur = cur->_left;
}
//不存在返回空
return nullptr;
}
//插入:1.空树(直接插入) 2.非空树(搜索+插入)还要判断数据是否存在
bool insert(const T& val)
{
//判断是否为空树
if (_root == nullptr)
{
_root = new Node(val);
return true;
}
//搜索插入的位置
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (cur->_val == val)
return false;
else if (cur->_val < val)
cur = cur->_left;
else
cur = cur->_right;
}
//确定新插入数据的左右位置
cur = new Node(val);
if (parent->_val < val)
parent->_right = cur;
else
parent->_left = cur;
return true;
}
//删除
bool erase(const T& val)
{
//1.判断根节点
if (_root == nullptr)
return false;
Node* cur = _root;
Node* parent = nullptr;
//查找
while (cur)
{
if (cur->_val == val)
break;
else if (cur->_val < val)
{
parent = cur;//更新节点
cur = cur->_right;
}
else
{
parent = cur;
cur = cur->_left;
}
}
//判断cur是否为空
if (cur == nullptr)
return false;
//删除:叶子or非叶子?
//1.叶子节点
if (cur->_left == nullptr && cur->_right == nullptr)
{
//判断删除的是否为根节点
if (cur == _root)
{
_root = nullptr;
}
else
{
if (parent->_left == cur)
parent->_left == nullptr;
else
parent->_right == nullptr;
}
delete cur;
}
//2.非叶子节点
//左边为空,右边不为空
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;
}
//左边不为空,右边为空
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;
}
//左右都不为空
else
{
//左右孩子都存在
//1.找左子树最右节点
Node* child = cur->_left;
parent = cur;
while (child->_right)
{
parent = child;
child = child->_right;
}
//2.最右节点的值覆盖cur位置的值
cur->_val = child->_val;
//3.重新链接
if (parent->_left == child)
parent->_left = child->_left;
else
parent->_right = child->_left;
//4.删除最右节点
delete child;
}
return true;
}
//中序遍历:是有序的
void inorder()
{
_inorder(_root);
cout << endl;
}
void _inorder(Node* root)
{
if (root)
{
_inorder(root->_left);
cout << root->_val << " ";
_inorder(root->_right);
}
}
private:
Node* _root;
};
4.二叉搜索树两种模型的简单实现
4.1 K模型
- 只有K作为关键码,结构中只需要存储Key即可,关键码即为需要搜索到的值
- 例子:给一个单词
word
,判断该单词是否正确 - 以单词集合中的每个单词作为key,构建一棵二叉搜索树
- 在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误
template <class K>
struct Node
{
K _key;
Node* _left;
Node* _right;
Node(const K& key = K())
:_key(key)
, _left(nullptr)
, _right(nullptr)
{}
};
template <class K>
class BST
{
public:
typedef Node<K> Node;
//构造函数
BST()
:_root(nullptr)
{}
//拷贝构造
BST(const BST<K>& key)//拷贝构造---深拷贝
{
//结构也要拷过来,走到什么位置,就把对应的节点创建出来
_root = copy(bst._root);
}
//递归拷贝
Node* copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* cur = new(root->_key);
cur->_left = copy(root->_left);
cur->_right = copy(root->_right);
return cur;
}
//析构函数
~BST()
{
if (_root)
destory(_root);
}
//销毁
void destory(Node* root)
{
if (root)
{
destory(root->_left);
destory(root->_right);
delete root;
root = nullptr;
}
}
//查找
Node* find(const K& key)
{
//从根节点开始查找
Node* cur = _root;
while (cur)
{
if (cur->_key == key)
return cur;
else if (cur->_key < key)
cur = cur->_right;
else
cur = cur->_left;
}
return nullptr;
}
//插入
bool insert(const K& key)
{
//判断是否为空树
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
//搜索插入的位置
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (cur->_key == key)
return false;
else if (cur->_key < key)
cur = cur->_right;
else
cur = cur->_left;
}
cur = new Node(key);
//确定新插入数据的左右位置
if (parent->_key < key)
parent->_right = cur;
else
parent->_left = cur;
return true;
}
//删除
bool erase(const K以上是关于高阶数据结构 | 二叉搜索树(Binary Search Tree)的主要内容,如果未能解决你的问题,请参考以下文章
数据结构05红-黑树基础----二叉搜索树(Binary Search Tree)