hello~ 很高兴见到大家! 这次带来的是C++中关于二叉搜索树这部分的一些知识点,如果对你有所帮助的话,可否留下你宝贵的三连呢? 个 人 主 页: 默|笙

二叉搜索树又称二叉排序树,因为中序遍历这棵树得到的是一组排好序的数(前提是这棵树没有重复的值)。这棵树要么是一棵空树,要么满足以下性质:

二叉树的增删查找效率取决与被查找的值在这棵树上面的深度,深度越大,查找效率越低。

关于二分查找(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)
{
_root = new Node(key);
}
Node* cur = _root;
Node* 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 (parent->_key > key)
{
parent->left = new Node(key);
}
else
{
parent->right = new Node(key);
}
}
//调用中序遍历需要传递实参_root
//我们在外面是无法拿到_root的,所以需要经过一些处理,将中序遍历函数放到private中
//再写一个public里的调用中序遍历的函数便可,这样能够拿到_root传递给函数。
////中序遍历
//void _InOrder(Node* _root)
//{
// if (!_root)
// {
// return;
// }
// _InOrder(_root->left);
// cout << _root->_key << " ";
// _InOrder(_root->right);
//}
//调用函数
void InOrder()
{
_InOrder(_root);
}
private:
//中序遍历
void _InOrder(Node* _root)
{
if (!_root)
{
return;
}
_InOrder(_root->left);
cout << _root->_key << " ";
_InOrder(_root->right);
}
Node* _root = nullptr;
};bool Insert(const K& key)
{
return _Insert(_root, key);
}
bool _Insert(Node*& _root, const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
if (key > _root->_key)
{
_Insert(_root->right, key);
}
else if (key < _root->_key)
{
_Insert(_root->left, key);
}
else
{
return false;
}
}//查找
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->right;
}
else if (key < cur->_key)
{
cur = cur->left;
}
else
{
return true;
}
}
return false;
}


//删除
bool Erase(const K& key)
{
Node* cur = _root;
Node* parent = nullptr;
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)
{
//若要删除节点是其父节点的左孩子
if (parent->left == cur)
{
parent->left = cur->right;
}
//要删除节点是其父节点的右孩子
else
{
parent->right = cur->right;
}
}
else
{
_root = _root->right;
}
delete cur;
}
//如果左子树不为空,右子树为空
else if (cur->right == nullptr)
{
if (cur != _root)
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
}
else
{
_root = _root->left;
}
delete cur;
}
//两个子树都不为空
else
{
//找到右子树的最小值节点
Node* RightMin = cur->right;
Node* RightMinParent = cur;
while (RightMin->left)
{
RightMinParent = RightMin;//存储一下最小值节点的父节点
RightMin = RightMin->left;
}
swap(cur->_key, RightMin->_key);//交换两个节点的值
RightMinParent->left = RightMin->right;
delete RightMin;
}
return true;
}
}
return false;
}
只有key作为关键码,结构中只需要存储key即可,关键码即为需要搜索到的值,搜索场景只需要判断key在不在。key的搜索场景实现的二叉搜索树支持增删查,但是不支持修改,因为修改key会破坏搜索树的结构。
key二叉搜索树代码:
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)
{
_root = new Node(key);
}
Node* cur = _root;
Node* 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 (parent->_key > key)
{
parent->left = new Node(key);
}
else
{
parent->right = new Node(key);
}
}
/*bool Insert(const K& key)
{
return _Insert(_root, key);
}
bool _Insert(Node*& _root, const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
if (key > _root->_key)
{
_Insert(_root->right, key);
}
else if (key < _root->_key)
{
_Insert(_root->left, key);
}
else
{
return false;
}
}*/
//调用中序遍历需要传递实参_root
//我们在外面是无法拿到_root的,所以需要经过一些处理,将中序遍历函数放到private中
//再写一个public里的调用中序遍历的函数便可,这样能够拿到_root传递给函数。
////中序遍历
//void _InOrder(Node* _root)
//{
// if (!_root)
// {
// return;
// }
// _InOrder(_root->left);
// cout << _root->_key << " ";
// _InOrder(_root->right);
//}
//调用函数
void InOrder()
{
_InOrder(_root);
}
//查找
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->right;
}
else if (key < cur->_key)
{
cur = cur->left;
}
else
{
return true;
}
}
return false;
}
//删除
bool Erase(const K& key)
{
Node* cur = _root;
Node* parent = nullptr;
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)
{
//若要删除节点是其父节点的左孩子
if (parent->left == cur)
{
parent->left = cur->right;
}
//要删除节点是其父节点的右孩子
else
{
parent->right = cur->right;
}
}
else
{
_root = _root->right;
}
delete cur;
}
//如果左子树不为空,右子树为空
else if (cur->right == nullptr)
{
if (cur != _root)
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
}
else
{
_root = _root->left;
}
delete cur;
}
//两个子树都不为空
else
{
//找到右子树的最小值节点
Node* RightMin = cur->right;
Node* RightMinParent = cur;
while (RightMin->left)
{
RightMinParent = RightMin;//存储一下最小值节点的父节点
RightMin = RightMin->left;
}
swap(cur->_key, RightMin->_key);//交换两个节点的值
RightMinParent->left = RightMin->right;
delete RightMin;
}
return true;
}
}
return false;
}
private:
//中序遍历
void _InOrder(Node* _root)
{
if (!_root)
{
return;
}
_InOrder(_root->left);
cout << _root->_key << " ";
_InOrder(_root->right);
}
Node* _root = nullptr;
};
}每一个关键码key,都有与之对应的值value,value可以是任意类型对象。树的结构中(节点)除了需要存储key还要存储对应的value,增/删/查还是以key为关键字走二叉树的规则进行比较,可以快速查找到key对应的value。key/value的搜索场景实现的二叉搜索树支持修改value,但不支持修改key,修改key会破坏树的结构。
以下是key/value二叉搜索树代码:
:
//插入
bool Insert(const K& key, const V& value)
{
if (!_root)
{
_root = new Node(key, value);
}
Node* cur = _root;
Node* 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 (parent->_key > key)
{
parent->left = new Node(key, value);
}
else
{
parent->right = new Node(key, value);
}
}
//调用函数
void InOrder()
{
_InOrder(_root);
}
//查找
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_key)
{
cur = cur->right;
}
else if (key < cur->_key)
{
cur = cur->left;
}
else
{
return cur;
}
}
return nullptr;
}
//删除
bool Erase(const K& key)
{
Node* cur = _root;
Node* parent = nullptr;
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)
{
//若要删除节点是其父节点的左孩子
if (parent->left == cur)
{
parent->left = cur->right;
}
//要删除节点是其父节点的右孩子
else
{
parent->right = cur->right;
}
}
else
{
_root = _root->right;
}
delete cur;
}
//如果左子树不为空,右子树为空
else if (cur->right == nullptr)
{
if (cur != _root)
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
delete cur;
}
else
{
_root = _root->left;
}
delete cur;
}
//两个子树都不为空
else
{
//找到右子树的最小值节点
Node* RightMin = cur->right;
Node* RightMinParent = cur;
while (RightMin->left)
{
RightMinParent = RightMin;//存储一下最小值节点的父节点
RightMin = RightMin->left;
}
swap(cur->_key, RightMin->_key);//交换两个节点的值
RightMinParent->left = RightMin->right;
delete RightMin;
}
return true;
}
}
return false;
}
private:
//中序遍历
void _InOrder(Node* _root)
{
if (!_root)
{
return;
}
_InOrder(_root->left);
cout << _root->_key << " " << _root->_value << " ";
_InOrder(_root->right);
}
Node* _root = nullptr;
};今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~ 让我们共同努力, 一起走下去!