二叉搜索树是一种特殊的二叉树,具有以下性质:
1. 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
2. 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
3. 它的左右子树也分别为二叉搜索树。
空树也是一颗二叉搜索树。二叉搜索树的中序遍历是有序的。
二叉搜索树的查找:
从根结点开始查找,若节点为空则返回 false;若不为空:1. 若节点大小小于要查找的节点,则从它右子树去找;2. 若节点大小大于要查找的节点,则从它的左子树去找;3. 若节点大小等于要查找的节点大小,则返回true。
二叉搜索树的插入:
如果为空树,则直接插入。若树不为空,则从根结点开始查找合适的位置进行插入:1. 若节点大小小于插入节点,则从右子树开始插入;2. 若节点大小大于插入节点,则从左子树开始插入;3. 若为空节点,则将节点插入该位置。
二叉搜索树的删除:
首先查找是否存在该节点,不存在返回false。如果存在: 1. 若要删除的节点的左子树为空,删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点。2. 若要删除的节点右子树为空,删除该节点且使被删除节点的双亲节点指向被删除节点的左孩子节点。3. 若要删除的节点左右子树都不为空,寻找该节点左子树的最大节点或者右子树的最小节点,将寻找到节点的值赋值给要删除的节点的值,然后删除找到的节点,代替删除。
二叉搜索树的实现:
#include<iostream>
using namespace std;
template<class T>
struct BSTNode
{
BSTNode(const T& value = T())
:left(nullptr), right(nullptr), val(value)
{
}
BSTNode* left;
BSTNode* right;
T val;
};
template<class T>
class BSTree
{
public:
BSTree() :root(nullptr)
{
}
BSTNode<T>* find(const T& value)
{
BSTNode<T>* cur = root;
while (cur)
{
if (value > cur->val)
cur = cur->right;
else if (value < cur->val)
cur = cur->left;
else
return cur;
}
return nullptr;
}
bool insert(const T& value)
{
if (root == nullptr)
{
root = new BSTNode<T>(value);
return true;
}
BSTNode<T>* cur = root;
BSTNode<T>* parent = nullptr;
while (cur)
{
if (cur->val > value)
{
parent = cur;
cur = cur->left;
}
else if (cur->val < value)
{
parent = cur;
cur = cur->right;
}
else
{
return false;
}
}
cur = new BSTNode<T>(value);
if (value < parent->val)
{
parent->left = cur;
}
else
{
parent->right = cur;
}
return true;
}
bool erase(const T& value = T())
{
if (nullptr == root)
{
return false;
}
BSTNode<T>* cur = root;
BSTNode<T>* parent = nullptr;
while (cur)
{
if (cur->val > value)
{
parent = cur;
cur = cur->left;
}
else if (cur->val < value)
{
parent = cur;
cur = cur->right;
}
else
{
if (cur->left == nullptr)
{
if (cur == parent->left)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
}
else if (cur->right == nullptr)
{
if (cur == parent->left)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
}
else
{
BSTNode<T>* min_right = cur->right;
parent = cur;
while (min_right->left)
{
parent = min_right;
min_right = min_right->left;
}
cur->val = min_right->val;
if (min_right == parent->left)
{
parent->left = min_right->right;
}
else
{
parent->right = min_right->right;
}
delete min_right;
min_right = nullptr;
}
return true;
}
}
return false;
}
void inorder()
{
_InOrder(root);
cout << endl;
}
~BSTree()
{
_Destroy(root);
}
private:
BSTNode<T>* root;
void _InOrder(BSTNode<T>* _root)
{
if (_root)
{
_InOrder(_root->left);
cout << _root->val << " ";
_InOrder(_root->right);
}
}
void _Destroy(BSTNode<T>* &_root)
{
if (_root)
{
_Destroy(_root->left);
_Destroy(_root->right);
_root = nullptr;
}
}
};
int main()
{
BSTree<int> bst;
bst.insert(6);
bst.insert(4);
bst.insert(8);
bst.insert(3);
bst.insert(5);
bst.insert(7);
bst.insert(9);
bst.inorder();
bst.erase(4);
bst.inorder();
system("pause");
return 0;
}
二叉搜索树的性能分析:
对于一个关键码集合,如果插入顺序不同,得到的二叉搜索树也不同。
查找时间复杂度:
1. 最佳的情况下,二叉搜索树为完全二叉树,时间复杂度为 O(log2N)
2. 最差的情况下,二叉搜索树退化为单支树,相当于一个链表,时间复杂度为O(N)