一.二叉搜索树的概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
3.它的左右子树也分别为二叉搜索树。
二.二叉搜索树的查找
1.从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
2.最多查找高度次,走到到空,还没找到,这个值不存在。
三.二叉搜索树的插入
插入的具体过程如下:
1.树为空,则直接新增节点,赋值给root指针。
2. 树不空,按二叉搜索树性质查找插入位置,插入新节点。
四.二叉搜索树的删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
1.要删除的结点无孩子结点。
2.要删除的结点只有左孩子结点。
3.要删除的结点只有右孩子结点。
4.要删除的结点有左、右孩子结点。
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:
情况2:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除。
情况3:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除。
情况4:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除。
五.二叉搜索树的简单实现
#include <iostream>
using namespace std;
template<class T>
struct BSTNode
{
BSTNode(const T& data=T())
:_left(nullptr)
,_right(nullptr)
,_data(data)
{}
BSTNode<T>* _left;
BSTNode<T>* _right;
T _data;
};
template<class T >
class BSTree
{
typedef BSTNode<T> Node;
public:
bool Insert(const T& data)
{
if (nullptr == _root)
{
_root = new Node(data);
return true;
}
Node* parent = nullptr;
while (cur)
{
parent = cur;
if (cur->_data > data)
{
cur = cur->_left;
}
else if (cur->_data < data)
{
cur = cur->_right;
}
else
return false;
}
cur = new Node(data);
if (parent->_data < data)
parent->_right = cur;
else
parent->_left = cur;
return true;
}
void _InOrder(Node* root)
{
if (nullptr == root)
return;
_InOrder(root->_left)
cout << root->_data << " ";
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
}
bool Erase(const T& data)
{
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (cur->_data > data)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < data)
{
parent = cur;
cur = cur->_right;
}
else
{
//找到了所要删除的节点
//1.当要删除的节点的_left==nullptr
if (nullptr == cur->_left)
{
//这里要判断一下cur是否等于_root 判断条件是:parent==nullptr 或 cur==_root
if (cur == _root)
{
_root = cur->_right;
return true;
}
//要判断cur的_right是衔接再parent的_left还是_right
if (parent->_left == cur)
{
parent->_left = cur->_right;
return true;
}
else
{
parent->_left = cur->_right;
}
}
else if (nullptr == cur->_right)
{
if (cur == _root)
{
_root = cur->_left;
}
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
//要删除的节点(cur)的_left和_right都不为空
else
{
//找到右子树的最小节点(最左节点) 是相对于要删除的节点(cur)的右子树的最小节点
Node* parent = cur;
Node* subleft = cur->_right;
while (subleft->_left)
{
parent = subleft;
subleft = subleft->_left;
}
//交换要删除的节点(cur)和右子树的最小节点即右子树的最左节点的_data
swap(cur->_data, subleft->_data);
//再通过parent将与cur交换的subleft覆盖掉,这里覆盖情况有两种
if (parent->_left == subleft)
parent->_left = subleft->_right;//这里必须是sub->_right因为有可能subleft的_right不一定为空,
//subleft->_right不为空,subleft->_left为空,则subleft仍然是右子树最小节点
else
parent->_right = subleft->_right;
}
return true;
}
}
return false;
}
private:
Node* _root;
};