二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{}
};
两种情况:
// 非递归版本
bool Insert(const K& key)
{
// 1.树为空,直接新增结点
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
// 2.树不空,按二叉搜索树性质查找插入位置,插入新节点
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
parent = cur;
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
// 因为类外面拿不到根节点,但类里面可以,所以在类里面定义一个函数
// 通过类里面去调用
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
// 递归版本
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (root->_key < key)
{
return _InsertR(root->_right, key);
}
else if (root->_key > key)
{
return _InsertR(root->_left, key);
}
else
{
return false;
}
}
// 非递归版本
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 FindR(const K& key)
{
return _FindR(_root, key);
}
bool _FindR(Node* root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key < key)
{
return _FindR(root->_right, key);
}
else if (root->_key > key)
{
return _FindR(root->_left, key);
}
else
{
return true;
}
}
二叉树的删除情况比较复杂,首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
但是第一种情况可以和第二种或者第三种情况合并,所以删除过程有下面三种:
// 非递归版本
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 (cur == _root)
{
_root = cur->_right;
}
else
{
// 如果待删除节点是左孩子
// 则让待删除节点的右孩子赋给待删除节点的父节点的左孩子
if (cur == parent->_left)
{
parent->_left = cur->_right;
}
// 同理
else
{
parent->_right = cur->_right;
}
}
delete cur;
}
// 右孩子为空
else if (cur->_right == nullptr)
{
// 如果删除根节点,则直接将左孩子赋给根节点
if (cur == _root)
{
_root = cur->_left;
}
// 如果待删除节点是左孩子
// 则让待删除节点的左孩子赋给待删除节点的父节点的左孩子
else
{
if (cur == parent->_left)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
}
// 左右都不为空
else
{
// 右子树的最小节点(最左节点)
Node* parent = cur;
Node* subLeft = cur->_right;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
// 交换值
swap(cur->_key, subLeft->_key);
if (subLeft == parent->_left)
{
parent->_left = subLeft->_right;
}
else
{
parent->_right = subLeft->_right;
}
delete subLeft;
}
return true;
}
}
return false;
}
// 递归版本
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
bool _EraseR(Node*& root, const K& key)
{
if (root == nullptr)
return false;
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else
{
if (root->_left == nullptr)
{
Node* del = root;
root = root->_right;
delete del;
return true;
}
else if (root->_right == nullptr)
{
Node* del = root;
root = root->_left;
delete del;
return true;
}
else
{
// 右树的最小节点(最左节点)
Node* subLeft = root->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
swap(root->_key, subLeft->_key);
// 转换成在子树去递归删除
return _EraseR(root->_right, key);
}
}
}