bosthhe1 / cpushpush

0 stars 0 forks source link

搜索二叉树 #27

Open bosthhe1 opened 1 year ago

bosthhe1 commented 1 year ago

搜索二叉树是一种特殊的二叉树结构,二叉树的左孩子的值,永远比根节点值小,二叉树的右孩子的值,永远比根节点值大,所以搜索二叉树只需要将值进行比较,就能很快锁定值的位置,最好时间复杂度为高度次(log2N), 最坏的时间复杂度为O(N)单链表的形式,搜索二叉树的功能是排序+去重,只要构建出来,每一个节点就都会存在固定的位置。 由于搜索二叉树的特别性质,所以搜索二叉树的走中序,是一个从小到大的递增。 搜索二叉树的构建中,插入是很简单的,只要注意下需要带父节点,或者带二级指针改变节点的链接即可,但是删除很麻烦,删除的话需要分情况,如果删除的节点没有孩子或者只有一个孩子,就可以直接托孤,将节点的孩子给父亲,但是需要注意的节点时父节点的哪一个孩子,如果删除节点是有两个孩子,就需用到替换的方法,将值替换掉,这个值必须满足比左边所有节点都打,比右边所有节点都小,所有就会存在两个值,这种情况随便选一个交换即可,交换后,问题变为删除被替换的节点,哪个节点一定是一个极端,要么没有孩子,要么只有一个左孩子或者右孩子,这时候再来处理就方便很多

bosthhe1 commented 1 year ago
template<class T>
class BSTree
{

    typedef BSNode<T> BSNode;
public:
    BSTree(const T a = T())
        :node(new BSNode(a))
    {}
    bool insertNode(const T key)
    {
        BSNode* parent = node;
        BSNode* cur = node;
        while (cur)
        {
            if (cur->a < key)
            {
                parent = cur;
                cur = cur->right;
            }
            else if (cur->a > key)
            {
                parent = cur;
                cur = cur->left;
            }
            else
                return false;
            if (cur == nullptr)
            {
                BSNode* newnode =new BSNode(key);
                if (parent->a > key)
                {
                    parent->left = newnode;
                }
                else
                {
                    parent->right = newnode;
                }
            }
        }
    }
    bool Erase(const T& key)
    {
        return _Erase(node,key);
    }
    bool RErase(const T& key)
    {
        return _RErase(node, key);
    }
    BSNode* find(const T& key)
    {
        return _find(node, key);
    }
    void inorder()
    {
        _inorder(node);
    }
    BSNode* Rfind(const T& key)
    {
        return _Rfind(node,key);
    }
    bool RinsertNode(const T key)
    {
        return _RinsertNode(node, key);
    }
private:
    bool _RinsertNode(BSNode*& root, const T& key)
    {
        if (root == nullptr)
        {
            root = new BSNode(key);
            return true;
        }
        if (root->a > key)
        {
            return _RinsertNode(root->left, key);
        }
        else if (root->a < key)
        {
            return _RinsertNode(root->right, key);
        }
        else
            return false;
    }
    BSNode* _Rfind(BSNode* root,const T& key)
    {
        if (root == nullptr)
        {
            return nullptr;
        }
        if (root->a > key)
        {
            return _Rfind(root->left, key);
        }
        else if (root->a < key)
        {
            return _Rfind(root->right, key);
        }
        else
            return root;
    }
    bool _RErase(BSNode*& root, const T& key)
    {
        if (root == nullptr)
            return false;
        if (root->a > key)
        {
            return _RErase(root->left, key);
        }
        else if (root->a < key)
        {
            return _RErase(root->right, key);
        }
        else
        {

            if (root->left == nullptr)
            {
                root = root->right;
            }
            else if (root->right==nullptr)
            {
                root = root->left;
            }
            else
            {
                BSNode* min = root->left;
                while (min->right)
                {
                    min = min->right;
                }
                std::swap(root->a, min->a);
                _RErase(root->left, key);
                return true;
            }   
        }
    }
    bool _Erase(BSNode* root, const T& key)
    {
        BSNode* cur = root;
        BSNode* parent = root;
        while (cur)
        {
            if (cur->a > key)
            {
                parent = cur;
                cur = cur->left;
            }
            else if (cur->a < key)
            {
                parent = cur;
                cur = cur->right;
            }
            else//cur->a ==key
            {
                BSNode* del = cur;
                //左为空,或者又为空
                if (cur->left == nullptr || cur->right == nullptr)
                {
                    if (parent->left == cur)
                    {
                        if (cur->left == nullptr)
                        {
                            parent->left = cur->right;
                        }
                        else if (cur->right == nullptr)
                        {
                            parent->left = cur->left;
                        }
                    }
                    else
                    {
                        if (cur->left == nullptr)
                        {
                            parent->right = cur->right;
                        }
                        else if (cur->right == nullptr)
                        {
                            parent->right = cur->left;
                        }
                    }
                    delete cur;
                    return true;
                }
                //都不为空,使用的是交换法,将左子树的最大值,或者右子树的最小值进行交换,然后将key值删除,因为交换后key的左孩子或者有孩子一定为空,因为遍历的就是最左或最右(所以不存在节点有两个孩子都不为空的情况。),所以再用前面的方法删除节点
                else
                {
                    BSNode* min = cur->left;
                    BSNode* minparent = cur;
                    while (min->right)//找左最大替换 ,min节点可能存在右孩子,如果有右孩子会递归下去
                    {
                        minparent = min;
                        min = min->right;
                    }
                    cur->a = min->a;
                    if (minparent->left == min)//这里是确认孩子是左孩子还是右孩子
                    {
                        minparent->left = min->left; //min的右边为空,只能直向左边
                    }
                    else
                    {
                        minparent->right = min->left;//min的右边为空,只能直向左边
                    }
                    delete min;
                    return true;
                }
            }
        }
        return false;
    }
    BSNode* _find(BSNode* root, const T& key)
    {
        BSNode* cur = root;
        while (cur)
        {
            if (cur->a>key)
            {
                cur = cur->left;
            }
            else if (cur->a < key)
            {
                cur = cur->right;
            }
            else if (cur == nullptr)
                return nullptr;
            else
                return cur;
        }
    }
    void _inorder(BSNode* root)
    {
        if (root == nullptr)
            return;
        _inorder(root->left);
        std::cout << root->a << " ";
        _inorder(root->right);
    }
private:
    BSNode* node;
};