二叉搜索树的创建和定义,基本操作,递归形式的基本操作。

二叉搜索树的定义

二叉搜索树的结构,查找元素是非常方便的,将大大减少遍历查找的时间复杂度,它是特殊的二叉树,所以它的定义和二叉树一样

typedef int D_TYPE;

typedef struct BSTree
{
    struct BSTree* _Left;
    struct BSTree* _Right;
    D_TYPE data;
}BSTree,*pBSTree;

二叉搜索树增加元素

二叉搜索树的每个结点的数据,都比自己的左孩子大,比右孩子小。所以在增加元素的时候也必须遵循这个规则,元素增加代码如下:

bool BSTreeInsert(pBSTree* Bst,D_TYPE d)
{
    pBSTree cur = *Bst;
    pBSTree pre = NULL;
    int ret;
    assert(Bst);
    if(NULL == *Bst)
    {
        *Bst = BuyBSTree(d);
        return true;
    }
    else
    {
        while(cur)
        {
            pre = cur;
            if(d < cur->data)
            {
                ret = 1;
                cur = cur->_Left;
            }
            else if(d > cur->data)
            {
                ret = 0;
                cur = cur->_Right;
            }
            else
                return false;
        }
        if(1 == ret)
            pre->_Left = BuyBSTree(d);
        else
            pre->_Right = BuyBSTree(d);
        return true;
    }
}

返回bool类型是为了判断是否增加成功,函数首先判断头结点指针是否为空,如果是空就得让头结点指向第一个创建的节点,这也是函数传参为什么传二级指针。如果头结点不为空,让cur走向循环,用pre保存cur,为了保存cur的前一个,最后找到位置的时候用pre->next来增加新元素。如果找到重复元素就返回失败。

二叉搜索树删除元素

删除元素也必须得遵循规则,增加元素无非就是找到增加的位置然后让上一个next指针指向他,但是删除元素删除之后会打破原本的二叉搜索树的结构,具体代码如下:

bool BSTreeErase(pBSTree* Bst,D_TYPE d)
{
    pBSTree del = *Bst;
    pBSTree pre = *Bst;
    pBSTree cur = NULL;
    assert(Bst);
    if(NULL == *Bst)
        return false;
    while(del)
    {

        if(d == del->data)
            break;
        else if(d < del->data)
        {
            pre = del;
            del = del->_Left;
        }
        else
        {
            pre = del;
            del = del->_Right;
        }
    }
    if(NULL == del)
        return false;
    if(NULL == del->_Left)
    {
        if(pre == del)
        {
            *Bst = del->_Right;
            return true;
        }
        if(pre->_Left == del)
            pre->_Left = del->_Right;
        else
            pre->_Right = del->_Right;
        return true;
    }
    else if(NULL == del->_Right)
    {
        if(pre == del)
        {
            *Bst = del->_Left;
            return true;
        }
        if(pre->_Left == del)
            pre->_Left = del->_Left;
        else
            pre->_Right = del->_Left;
        return true;
    }
    else
    {
        cur = del->_Right;
        pre = del;
        while(cur->_Left)
        {
            pre = cur;
            cur = cur->_Left;
        }
        del->data = cur->data;
        if(pre == del)
            pre->_Right = cur->_Right;
        else
            pre->_Left = cur->_Right;
        return false;
    }
}

用第一个循环来找到需要删除的那个元素的节点,找不到就返回false。找到需要删除的结点之后,有三种情况:
1.只有右结点(或者是叶子节点)
如果只有右结点,要删除它,只需要让它的双亲节点,指向它的右结点,把它跳过去就行了。如图:
这里写图片描述
2.只有左结点
和上面的只有右结点同理,值得注意的是,这两个情况都有一个特殊可能就是,del就是二叉搜索树头结点所指向的结点,那么他是没有pre的。所以我们在函数一开始就将pre和del都赋值为头结点,所以当第一个循环结束,还检测到两个相等,就直接让头结点的指针指向del的Left或者Right。
3.左右节点都有
这是比较复杂的情况,解决方法是类似于替换法。就是将此节点右子树里面最小的元素值赋值给它(因为右子树都是大于它的,取最小元素才不会破坏右子树的结构),当然取左子树的最大的可以替换,这里以右子树的最小的为例,如图:
这里写图片描述
还有一个小问题就是del到底是pre的左孩子还是右孩子,需要用if去判断一下,大体思路是这样的,具体如何实现还得多调试完成。

递归完成基本操作

增加元素用递归完成代码:

bool BSTreeInsert_R(pBSTree* Bst,D_TYPE d)
{
    assert(Bst);
    if(NULL == *Bst)
    {
        *Bst = BuyBSTree(d);
        return true;
    }
    else if(d == (*Bst)->data)
        return false;
    else if(d <  (*Bst)->data)
        return BSTreeInsert_R(&(*Bst)->_Left,d);
    else
        return BSTreeInsert_R(&(*Bst)->_Right,d);
}

删除元素用递归完成代码:

{
    pBSTree cur;
    assert(Bst);
    if(NULL == (*Bst))
        return false;
    else if(d < (*Bst)->data)
        return BSTreeErase_R(&(*Bst)->_Left,d);
    else if(d > (*Bst)->data)
        return BSTreeErase_R(&(*Bst)->_Right,d);
    else
    {
        if(NULL == (*Bst)->_Left)
            *Bst = (*Bst)->_Right;
        else if(NULL == (*Bst)->_Right)
            *Bst = (*Bst)->_Left;
        else
        {
            cur = (*Bst)->_Right;
            while(cur->_Left)
                cur = cur->_Left;
            (*Bst)->data = cur->data;
            BSTreeErase_R(&(*Bst)->_Right,cur->data);
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39487033/article/details/82385952