1 理解二叉搜索树
1.1 二叉搜索树概念
- 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。
- 它的左右子树也分别为二叉搜索树。
1. 二叉搜索树的查找
a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。
2. 二叉搜索树的插入
插入的具体过程如下:
a. 树为空,则直接新增节点,赋值给root指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点
3. 二叉搜索树的删除
- 首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点 - a可以与情况b或者c合并起来,因此真正的删除过程
如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点
中,再来处理该结点的删除问题–替换法删除
int a[] = {8, 3, 1, 10, 6, 4, 7, 14, 13};
二叉搜索树实现
namespace Key
{
template<class T>
struct BSTNode
{
BSTNode(const T& data = T())
:_pleft(nullptr)
, _pright(nullptr)
, _data(data)
{}
BSTNode* _pleft;
BSTNode* _pright;
T _data;
};
template<class T>
class BSTree
{
typedef BSTNode<T> Node;
public:
bool Insert(const T& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* cur = _root;
Node* parent = _root;
while (cur) //迭代并去重
{
if (cur->_data < key)
{
parent = cur;
cur = cur->_pright;
}
else if (cur->_data > key)
{
parent = cur;
cur = cur->_pleft;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_data < key)
{
parent->_pright = cur;
}
else //此处不可能相等 <
{
parent->_pleft = cur;
}
return true;
}
bool Find(const T& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_data < key)
{
cur = cur->_pright;
}
else if (cur->_data > key)
{
cur = cur->_pleft;
}
else
{
return true;
}
}
return false;
}
bool Erase(const T& key)
{
if (_root == nullptr)
{
return false;
}
Node* parent = _root;
Node* cur = _root;
while (cur)
{
if (cur->_data < key)
{
parent = cur;
cur = cur->_pright;
}
else if (cur->_data > key)
{
parent = cur;
cur = cur->_pleft;
}
else
{
//开始删除 1. 左为空 2. 右为空 3. 左右都不为空
if (cur->_pleft == nullptr)
{
if (cur == _root)
{
_root = cur->_pright;
}
else
{
if (cur == parent->_pleft)
{
parent->_pleft = cur->_pright;
}
else
{
parent->_pright = cur->_pright;
}
}
delete cur;
cur = nullptr;
}
else if (cur->_pright == nullptr)
{
if (cur == _root)
{
_root = cur->_pleft;
}
else
{
if (cur == parent->_pleft)
{
parent->_pleft = cur->_pleft;
}
else
{
parent->_pright = cur->_pleft;
}
}
delete cur;
cur = nullptr;
}
else
{
//找右子树最小值,进行替换
Node* minparent = cur;
Node* min = cur->_pright;
while (min->_pleft)
{
minparent = min;
min = min->_pleft;
}
swap(cur->_data, min->_data);
//可能删除的结点右面有结点以及删除结点的位置
if (minparent->_pleft == min)
{
minparent->_pleft = min->_pright;
}
else
{
minparent->_pright = min->_pright;
}
delete min;
min = nullptr;
}
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
BSTree()
{}
~BSTree()
{
_Destory(_root);
}
private:
void _Destory(Node*& root)
{
if (root == nullptr)
{
return;
}
_Destory(root->_pleft);
_Destory(root->_pright);
delete root;
root = nullptr;
}
Node* _root = nullptr;
};
}
void TestBsTree1()
{
Key::BSTree<int> t;
int a[] = { 8, 3, 1, 10, 4, 6, 7, 14, 13, 4, 3, 4 };
for (auto e : a)
{
t.Insert(e);
}
//排序+去重
t.InOrder();
t.Erase(3);
t.InOrder();
t.Erase(10);
t.InOrder();
for (auto e : a)
{
t.Erase(e);
t.InOrder();
}
}