二叉搜索树的基本操作 ---- 插入,删除,查找,销毁,遍历

首先来看看二叉搜索树的概念
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

二叉搜索树的结构体

#define bool int
#define true 1
#define false 0
typedef int BDataType;
typedef struct BSTreeNode
{
    struct BSTreeNode* _pLeft;
    struct BSTreeNode* _pRight;
    BDataType _data;
}BSTNode;

初始化

void InitBSTree(BSTNode** pRoot)//初始化
{
    assert(pRoot);
    *pRoot = NULL;
}

插入
在二叉搜索树中插入新元素时,必须先检测该元素是否在数中已经存在。如果已经存在,则不进行插入;否则将新元素加入到搜索停止的地方。

BSTNode* BuyBSTreeNode(BDataType data)
{
    BSTNode* pNewNode = (BSTNode*)malloc(sizeof(BSTNode));
    if (pNewNode == NULL)
    {
        perror("malloc::BuyBSTreeNode");
        return NULL;
    }
    pNewNode->_data = data;
    pNewNode->_pLeft = NULL;
    pNewNode->_pRight = NULL;
    return pNewNode;
}
////非递归
bool InSertBSTree(BSTNode** pRoot, BDataType data)//插入
{
    BSTNode* parent = NULL;
    BSTNode* pNewNode = NULL;
    BSTNode* pCur = NULL;
    assert(pRoot);
    pCur = *pRoot;
    //空树 ---- 直接插入
    if (*pRoot == NULL)
    {
        *pRoot = BuyBSTreeNode(data);
        return true;
    }
    //找该结点在二叉搜索树中的插入位置
    while (pCur)
    {
        parent = pCur;
        if (data < pCur->_data)
            pCur = pCur->_pLeft;
        else if (data > pCur->_data)
            pCur = pCur->_pRight;
        else
            return false;
    }

    ///插入结点
    pNewNode = BuyBSTreeNode(data);
    if (data < parent->_data)
        parent->_pLeft = pNewNode;
    else
        parent->_pRight = pNewNode;
    return true;
}
/////递归
bool InSertBSTree(BSTNode** pRoot, BDataType data)//插入
{
    assert(pRoot);
    if (*pRoot == NULL)
    {
        *pRoot = BuyBSTreeNode(data);
        return true;
    }
    else
    {
        if (data == (*pRoot)->_data)
            return false;
        else if (data < (*pRoot)->_data)
            return InSertBSTree(&(*pRoot)->_pLeft, data);
        else
            return InSertBSTree(&(*pRoot)->_pRight, data);
    }
}

查找

/////////非递归
BSTNode* FindBSTree(BSTNode* pRoot, BDataType data)
{
    BSTNode* pCur = pRoot;
    while (pCur)
    {
        if (pCur->_data == data)
            return pCur;
        else if (data < pCur->_data)
            pCur = pCur->_pLeft;
        else
            pCur = pCur->_pRight;
    }
    return NULL;
}

/////递归
BSTNode* FindBSTree(BSTNode* pRoot, BDataType data)
{
    if (NULL == pRoot)
        return NULL;
    if (data == pRoot->_data)
        return pRoot;
    else if (data < pRoot->_data)
        return FindBSTree(pRoot->_pLeft, data);
    else
        return FindBSTree(pRoot->_pRight, data);
}

删除
删除比较复杂分为以下几种情况
首先查找元素是否在二叉搜索树中,如果不存在,则返回,否则要删除的结点可能分以下四种情况:
1.要删除的结点无孩子结点
2.要删除的结点只有左孩子结点
3.要删除的结点只有右孩子结点

情况1可以归类到2或3
对于上述情况,相应的删除方法如下:
1.直接删除该结点
2.删除该结点且使被删除结点的双亲结点指向被删除结点的左孩子结点
3.删除该结点且使被删除结点的双亲结点指向被删除结点的右孩子结点
4.在它的左子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除结点中,再来处理该结点的删除问题

///////非递归
bool DeleteBSTree(BSTNode** pRoot, BDataType data)//删除
{
    BSTNode* pCur = NULL;
    BSTNode* parent = NULL;
    assert(pRoot);
    if (*pRoot == NULL)
        return;
    pCur = *pRoot;
    parent = pCur;
    while (pCur)
    {

        if (data == pCur->_data)
            break;
        else if (data < pCur->_data)
        {
            parent = pCur;          ///要指向pCur的上一个结点
            pCur = pCur->_pLeft;
        }
        else
        {
            parent = pCur;
            pCur = pCur->_pRight;
        }
    }
    ///该元素不在二叉树中
    if (NULL == pCur)
        return false;

    ///在二叉搜索树中删除pCur所指向的节点
    if (NULL == pCur->_pLeft)
    {
        //待删除结点只有右孩子|| 叶子结点
        if (pCur == *pRoot)    //待删除结点为根节点
            *pRoot = pCur->_pRight;
        ////pCur不为根结点
        else
        {
            if (parent->_pLeft == pCur)
                parent->_pLeft = pCur->_pRight;
            else
                parent->_pRight = pCur->_pRight;
        }

    }
    else if (NULL == pCur->_pRight)
    {
        ///待删除节点只有左孩子
        if (pCur == *pRoot)
            *pRoot = pCur->_pLeft;
        else
        {
            if (parent->_pLeft == pCur)
                parent->_pLeft = pCur->_pLeft;
            else
                parent->_pRight = pCur->_pLeft;
        }
    }
    else
    {
        //待删除节点左右孩子都存在
        BSTNode* pInOrder = pCur->_pRight;
        //找中序遍历下的第一个结点(右子树中最左侧结点)
        while (pInOrder->_pLeft)
        {
            parent = pInOrder;
            pInOrder = pInOrder->_pLeft;
        }
        ///用该结点内容替换待删除结点中数据
        pCur->_data = pInOrder->_data;

        ////删除代替结点
        if (parent->_pLeft == pInOrder)
            parent->_pLeft = pInOrder->_pRight;
        else
            parent->_pRight = pInOrder->_pRight;
        pCur = pInOrder;
    }
    free(pCur);
    pCur = NULL;
    return true;
}


///////递归

bool DeleteBSTree(BSTNode** pRoot, BDataType data)//删除
{
    assert(pRoot);
    if (*pRoot == NULL)
        return false;
    if (data < (*pRoot)->_data)
        return DeleteBSTree(&(*pRoot)->_pLeft, data);
    else if (data > (*pRoot)->_data)
        return DeleteBSTree(&(*pRoot)->_pRight, data);
    else
    {
        BSTNode* pDelNode = *pRoot;
        if (NULL == pDelNode->_pLeft)
        {
            *pRoot = pDelNode->_pRight;
            free(pDelNode);
            pDelNode = NULL;
            return true;
        }
        else if (NULL == pDelNode->_pRight)
        {
            *pRoot = pDelNode->_pLeft;
            free(pDelNode);
            pDelNode = NULL;
            return true;
        }
        else
        {
            BSTNode* pInOrder = pDelNode->_pRight;
            while (pInOrder->_pLeft)
                pInOrder = pInOrder->_pLeft;
            pDelNode->_data = pInOrder->_data; //将要删除的结点替换
            return DeleteBSTree(&(*pRoot)->_pRight, pInOrder->_data);//去要删除结点的右子树中找替换后要删除的结点,并删除
        }
    }
}

销毁

void DestroyBSTree(BSTNode** pRoot)//销毁
{
    assert(pRoot);
    if (*pRoot)
    {
        DestroyBSTree(&(*pRoot)->_pLeft);
        DestroyBSTree(&(*pRoot)->_pRight);
        free(*pRoot);
        *pRoot = NULL;
    }
}

中序遍历

void InOrder(BSTNode* pRoot)//中序遍历
{
    if (pRoot)
    {
        InOrder(pRoot->_pLeft);
        printf("%d   ", pRoot->_data);
        InOrder(pRoot->_pRight);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39032310/article/details/82382608