二叉搜索树结点的查找、插入、删除

       二叉搜索树(Binary Search Tree,BST),要么是一颗空树,要么是一颗具有如下性质的二叉树:对于二叉搜索树的任意结点来说,若它的左子树非空,则左子树上所有结点的值均小于它的值; 若它的右子树不空,则右子树上所有结点的值均大于它的值; 它的左、右子树也分别为二叉搜索树。

       定义一颗二叉搜索树的结点结构如下:

struct BST_Node
{
    int val;
    BST_Node *left;
    BST_Node *right;
    BST_Node(int x) : val(x), left(nullptr), right(nullptr){}
};

       基于二叉搜索树的特点,其查找结点值的方式与普通二叉树不同。为了维护二叉搜索树的特点,其结点的插入、删除操作也比较特殊。

查找

       二叉搜索树的查找比较简单,结合二叉搜索树左子树比根小,右子树比根大的特点,只需要将查找值与结点值作比较,判断下一步往左子树走还是右子树走就可以了。

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;
}

       递归版本:

BST_Node* searchBST(BST_Node *root, int val)
{
    if (root == nullptr)
    {
        return root;
    }
    if (root->val < val)
    {
        return searchBST(root->right, val);
    }
    else if (root->val > val)
    {
        return searchBST(root->left, val);
    }
    return root;
}

 

       和二分查找中每次迭代之后查找的区间就会减半一样,在二叉查找树中,随着我们不断向下查找,当前结点所表示的子树大小也在减小(理想情况下是减半,但至少会减少一个结点)。当找到一个含有被查找的键的结点或者当前子树为空时才会结束。 

插入

        二叉搜索树的一个重要特性之一就是插入的实现难度和查找差不多。按照查找规则,找到合适的位置插入结点即可。

BST_Node* insertBST(BST_Node *root, int val)
{
    if (root == nullptr)
    {
        root = new BST_Node(val);
        return root;
    }
    BST_Node *parent = nullptr, *cur = root;
    while (cur != nullptr)
    {
        parent = cur;
        if (cur->val < val)
        {
            cur = cur->right;
        }
        else if (cur->val > val)
        {
            cur = cur->left;
        }
        else
        {
            return nullptr;
        }
    }
    if (parent->val < val)
    {
        parent->right = new BST_Node(val);
        return parent->right;
    }
    else
    {
        parent->left = new BST_Node(val);
        return parent->left;
    }
    return nullptr;
}

       递归版本较为简洁:

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;
}

 

删除

        二叉搜索树的结点删除较难实现,首先我们先要找到待删除的结点,若不存在则返回空,否则需要分为以下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;
        }
    }
}

 

       

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/qq_37653144/article/details/83069931
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞