二叉搜索树(Binary Search Tree),(又:二叉查找树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树:
1.若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2.若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3.它的左、右子树也分别为二叉排序树。
struct BST_Node
{
int val;
BST_Node *left;
BST_Node *right;
BST_Node(int x) : val(x), left(nullptr), right(nullptr){}
};
二叉搜索树的操作`
1.二叉搜索树的查找
若根节点不为空:
如果根节点key==查找key 返回true
如果根节点key>查找key 在其左子树查找
如果根节点key<查找key 在其右子树查找
否则 返回false
BST_Node* searchBST(BST_Node *root, int val)
{
while (root != nullptr)
{
if (root->val < val)
{
root = root->right;
}
else if (root->val > val)
{
root = root->left;
}
else
{
break;
}
}
return root;
}
2.二叉搜索树的插入
若树为空,则直接插入 然后返回true
若树不空,按二叉搜索树性质查找插入位置,插入新节点
BST_Node* insertBST(BST_Node *root, int val) {
if (root == nullptr)
{
root = new BST_Node(val);
return root;
}
if (root->val < val)
{
return insertBST(root->right, val);
}
else if (root->val > val)
{
return insertBST(root->left, val);
}
return nullptr;
}
3.二叉搜索树的删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情况:
- 要删除的结点无孩子结点
- 要删除的结点只有左孩子结点
- 要删除的结点只有右孩子结点
- 要删除的结点有左、右孩子结点
看起来有待删除节点有4种情况,实际情况1可以与情况2或者3合并起来,因此真正的删除过程如下:
情况2:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
情况3:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
情况4:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题
void deleteBST_Node(BST_Node *root, int val)
{
if (root == nullptr)
{
return ;
}
BST_Node *parent = nullptr, *cur = root;
while (cur != nullptr)
{
if (cur->val < val)
{
parent = cur;
cur = cur->right;
}
else if (cur->val > val)
{
parent = cur;
cur = cur->left;
}
else { //找到待删除结点
BST_Node *del = cur;
if (cur->left == nullptr && cur->right == nullptr) //左右子树都为空
{
if (parent->left == cur)
parent->left = nullptr;
else if (parent->right == cur)
parent->right = nullptr
delete cur;
}
else if (cur->left != nullptr && cur->right != nullptr) //左右子树都不为空
{
del = cur->right;
while (del->left != nullptr)
{
parent = del;
del = del->left;
}
cur->val = del->val;
if (del == cur->right)
{
parent->right = del->right;
}
else
{
parent->left = del->right;
}
delete del;
}
else //左右子树其中一个为空
{
if (cur->left != nullptr)
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
}
else
{
if (parent->left == cur)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
}
delete cur;
}
break;
}
}
}