一、二叉搜索数的定义
二叉搜索树(BST,Binary Search Tree)是一种特殊的二叉树,它具有以下性质:
- 每个节点都有一个唯一的键值。
- 左子树上所有节点的键值小于它的根节点的键值。
- 右子树上所有节点的键值大于它的根节点的键值。
- 左、右子树也分别是二叉搜索树。
这种结构使得二叉搜索树在进行查找、插入和删除操作时,平均时间复杂度达到O(log n),是一种高效的查找树。
按照这样存储数据,将二叉搜索树进行中序遍历后,结果是升序的。
二、二叉搜索树的实现
2.1二叉搜索树的结点
template<class K,class V>
struct BSTreeNode
{
BSTreeNode(const K& key = K())
:_key(key),
_right(nullptr),
_left(nullptr){}
K _key;BSTreeNode<K,V>* _right;
BSTreeNode<K,V>* _left;
};
2.2二叉搜索树的框架
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
bool Insert(const K& key);
Node* Find(const K& key);
bool Erase(const K& key);
void InOrder();
private:
void _InOrder(Node* root);
Node* _root = nullptr;
};
2.3二叉搜索树的插入
//实现节点的插入
bool Insert(const K& key)
{
//若是空树,就让其成为根节点
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
//若不是空树寻找该节点所在位置,并记录父节点
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else if (key > cur->_key)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;//已有结点,插入失败
}
}
//如果key较小,成为左子树,较大,则成为右子树
if (key < parent->_key) parent->_left = new Node(key);
else parent->_right = new Node(key);
return true;
}
2.4二叉搜索树的查找
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if(key==cur->_key)
return cur;
if (key < cur->_key) cur = cur->_left;
else(key > cur->_key) cur = cur->_right;
}
return nullptr;
}
2.4二叉搜索树的删除
分为四种情况
a. 要删除的结点无孩子
b. 要删除的结点只有左孩子
c. 要删除的结点只有右孩子
d. 要删除的结点有左、右孩子
bool Erase(const K& key)
{
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key == key)//找到了,进行删除操作
{
if (parent == nullptr)//查找到的结点为根节点
{
delete cur;
_root = cur = nullptr;
}
else
{
if (cur->_right == nullptr && cur->_left == nullptr)//没有孩子
{
if (parent->_key < cur->_key)
parent->_right = nullptr;
else
parent->_left = nullptr;
delete cur;
cur = nullptr;
}
else if (cur ->_right == nullptr && cur->_left != nullptr)//只有左孩子
{
if (parent->_key < cur->_key)
parent->_right = cur->_left;
else
parent->_left = cur->_left;
delete cur;
cur = nullptr;
}
else if (cur ->_right != nullptr && cur->_left == nullptr)//只有右孩子
{
if (parent->_key < cur->_key)
parent->_right = cur->_right;
else
parent->_left = cur->_right;
delete cur;
cur = nullptr;
}
else {//两个孩子,找右子树最小结点
Node* obj = cur->_right;
Node* objparent = cur;
while (obj->_left)
{
objparent = obj;
obj = obj->_left;
}
cur -> _key = obj -> _key;
if (objparent == cur)
cur->_right = obj->_right;
else
objparent->_left = obj->_right;
delete obj;
obj = nullptr;
}
}
return true;
}
parent = cur;//继续查找
if (cur->_key < key)
cur = cur->_right;
else
cur = cur->_left;
}
return false;
}
2.5二叉树的前序遍历
由于会使用到成员变量_root,所以可以制造接口InOrder()以便使用
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key <<" ";
_InOrder(root->_right);
}
2.6二叉树的拷贝
BSTree() = default; // 强制生成默认构造
Node* Copy(Node* root)
{
if (root == nullptr) return nullptr;
Node* newroot = new Node(root->_key);
newroot->_left = Copy(root->_left);
newroot->_right = Copy(root->_right);
return newroot;
}
BSTree(const BSTree<K>& t)
{
_root = Copy(t._root);
}
2.7二叉树赋值的现代写法
BSTree<K>& operator=(BSTree<K> t)
{
swap(_root, t._root);
return *this;
}
2.8二叉树的销毁
//销毁
void Destroy(Node*& root)
{
if (root == nullptr)
return;
//后续遍历,删左 删右 再删中间
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr;
}
~BSTree()
{
Destroy(_root);
}