二叉搜索树的基本操作

#pragma once
typedef int DataType;

typedef struct BSTreeNode
{
    struct BSTreeNode* _pLeft;
    struct BSTreeNode* _pRight;
    DataType _data;
}BSTNode;

#include<assert.h>
#include<stdio.h>
#include<stdlib.h>

BSTNode* BuyBSTreeNode(DataType data)
{
    BSTNode* pNewNode = (BSTNode*)malloc(sizeof(BSTNode));
    if(NULL == pNewNode)//申请失败的话
    {
        assert(0);
        return NULL;
    }
    pNewNode->_data =  data;
    pNewNode->_pLeft = NULL;
    pNewNode->_pRight = NULL;
    return pNewNode;
}
void BSTreeInit(BSTNode** pRoot)
{
    assert(pRoot);
    *pRoot = NULL;

}

void BSTreeInsert(BSTNode** pRoot,DataType data)//非递归的
{
    BSTNode* pCur = NULL;
    BSTNode* pParent = NULL;
    assert(pRoot);
    if(*pRoot == NULL)
    {

        *pRoot = BuyBSTreeNode(data);
        return;
    }
    //1、找待插入节点的插入位置
    pCur = *pRoot;//从根的位置找
    while(pCur)
    {
        if(data < pCur->_data)
        {
            pParent = pCur;
            pCur = pCur->_pLeft;//往左边走
        }
        else if(data >pCur->_data)
        {
            pParent = pCur;
            pCur = pCur->_pRight;//往后边走
        }
        else//说明已经存在了
            return;
    }
    //2、插入新节点
    pCur = BuyBSTreeNode(data);
    if(data < pParent->_data)//如果插入的新数据小于双亲的数据往左边插
        pParent->_pLeft = pCur;
    else
        pParent->_pRight = pCur;
}
void BSTreeInsert(BSTNode** pRoot,DataType data)//递归的
{
    assert(pRoot);//保证树存在
    if(NULL == *pRoot)//树是空的
        *pRoot = BuyBSTreeNode(data);
    else
    {
        if(data < (*pRoot)->_data)//要插入的数据小于根节点的data,往左边插
            BSTreeInsert(&(*pRoot)->_pLeft,data);
        else if(data > (*pRoot)->_data)//往右边插
            BSTreeInsert(&(*pRoot)->_pRight,data);
        else //已经找到了
            return;
    }


}

void BSTreeDelete(BSTNode** pRoot,DataType data)//删除结点(非递归的)
{
    BSTNode* pCur = NULL;
    BSTNode* pParent = NULL;
    assert(pRoot);
    pCur = *pRoot;
    //1、找待删除结点在二叉搜索树中的位置
    while(pCur)
    {
        if(data == pCur->_data)
            break;
        else if(data < pCur->_data)
        {
            pParent = pCur;
            pCur = pCur->_pLeft;
        }
        else
        {
            pParent = pCur;//保存双亲
            pCur = pCur->_pRight;
        }
    }
    if(pCur == NULL)
        return;
    //只有右孩子 或者 是叶子节点
    if(pCur->_pLeft == NULL)
    {
        if(pCur == *pRoot)
        {
            *pRoot = pCur->_pRight;

        }
        else
        {
            //检测待删除结点是其双亲的左还是右
            if(pParent->_pLeft == pCur)//pCur是双亲的左孩子
            pParent->_pLeft = pCur->_pRight;
            else//是双亲的右孩子
            pParent->_pRight = pCur->_pRight;
        }

    }
    else if(NULL == pCur->_pRight)//只有左孩子
    {

        if(pCur == *pRoot)//如果删除的是根
            *pRoot = pCur->_pLeft;//根指向当前的左子树
        else//不是根
        {
            if(pParent->_pLeft == pCur)//如果是双亲的左孩子
                pParent->_pLeft = pCur->_pLeft;
            else//双亲的右孩子
                pParent->_pRight = pCur->_pLeft;    
        }
    }
    else
    {
        //左右孩子都存在
         //在右子树中找最左侧的结点,也就是最小的结点。
        BSTNode* pDel = pCur->_pRight;//先让它走到右子树的那边,然后再找最左边的结点
        pParent = pCur;
        while(pDel->_pLeft)
        {   
            pParent = pDel;
            pDel = pDel->_pLeft;

        }
        pCur->_data = pDel->_data;//在右子树中删除pDel
        if(pDel == pParent->_pLeft)//要删除的pDel是双亲的左孩子
            pParent->_pLeft = pDel->_pRight;
        else
            pParent->_pRight = pDel->_pRight;
        pCur = pDel;
    }
    free(pCur);
}

void BSTreeDelete(BSTNode** pRoot,DataType data)//删除结点(递归的)
{

    assert(pRoot);//保证树存在
    if(NULL == *pRoot)//树是空的
        return;
    else
    {
        if(data < (*pRoot)->_data)//要插入的数据小于根节点的data,在左边删除data
            BSTreeDelete(&(*pRoot)->_pLeft,data);
        else if(data > (*pRoot)->_data)//在右边删除data
            BSTreeDelete(&(*pRoot)->_pRight,data);
        else //在根的位置
        {
            //左孩子为空,只有右孩子或者叶子节点
            BSTNode* pDel = *pRoot;
            if(NULL == pDel->_pLeft)
            {
                *pRoot = pDel->_pRight;
                free(pDel);     
            }
            else if(NULL == pDel->_pRight)  //只有左孩子
            {

                *pRoot = pDel->_pLeft;
                free(pDel);

            }
            else//左右孩子都存在
            {
                pDel = (*pRoot)->_pRight;//在右子树中找替代结点

                while(pDel->_pLeft)//在右子树中找最左边的结点
                    pDel = pDel->_pLeft;//一直在左边找

                (*pRoot)->_data = pDel->_data;//替代结点的数据交给待删除结点

                BSTreeDelete(&(*pRoot)->_pRight,pDel->_data);//pDel在pRoot的右子树中,然后再在pRoot的右子树中删除pDel的data

            }
        }
    }
}

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

BSTNode* BSTreeFind(BSTNode* pRoot,DataType data)//递归的
{
    if(NULL == pRoot)//这个树为空
        return NULL;
    else//这个树不为空
    {
        if(data == pRoot->_data)// 删除的结点是不是根节点
            return pRoot;
        else if(data < pRoot->_data)//要找的这个是数小于根节点的data。在左子树中找
            return BSTreeFind(pRoot->_pLeft,data);//在左子树中递归找data
        else
            return BSTreeFind(pRoot->_pRight,data);//在右子树中递归找data

    }

}

void InOrder(BSTNode* pRoot)//中序遍历
{
    if(pRoot)//如果这个树不为空
    {
        InOrder(pRoot->_pLeft);
        printf("%d ",pRoot->_data);
        InOrder(pRoot->_pRight);
    }

}
void BSTreeDestroy(BSTNode** pRoot)
{
    assert(pRoot);
    if(*pRoot)
    {
        BSTreeDestroy(&(*pRoot)->_pLeft);//先销毁左子树
        BSTreeDestroy(&(*pRoot)->_pRight);//销毁右子树
        free(*pRoot);
        *pRoot = NULL;   
    }

}



void TestBSTree()
{
    int a[] = {5,3,4,1,7,8,2,6,0,9};
    int i = 0;
    BSTNode* pRoot;
    BSTreeInit(&pRoot);
    for(;i < sizeof(a)/sizeof(a[0]);++i)
    {
        BSTreeInsert(&pRoot,a[i]);
    }
    printf("中序遍历的结果:");
    InOrder(pRoot);
    printf("\n");

    BSTreeInsert(&pRoot,10);

    BSTreeDelete(&pRoot,2);

    printf("中序遍历的结果:");
    InOrder(pRoot);
    printf("\n");

    BSTreeDelete(&pRoot,1);
    printf("中序遍历的结果:");
    InOrder(pRoot);
    printf("\n");
    //分别删除5 和 7
    BSTreeDelete(&pRoot,5);
    //BSTreeDelete(&pRoot,7);

    printf("中序遍历的结果:");
    InOrder(pRoot);
    printf("\n");

    BSTreeDestroy(&pRoot);
    //BSTreeDelete(&pRoot,2);
}

//1、删除的该结点左右孩子均为空(叶子)-----直接删除
//2、删除的该结点只有左孩子------直接删除
//3、删除的该结点只有右孩子------直接删除
        /*(1)待删除的结点没有双亲
        (2)待删除节点是其双亲的左或者右
                    (1)是双亲的左:pParent->left = pCur->right
                    (2)是双亲的右:pParent->right = pCur->right*/
//4、删除的该结点左右孩子都存在:一、在左子树或者右子树找替代结点
                        //(1)、左子树中找替代---找左子树中最大的结点
                        //(2)、右子树中找替代---找右子树中最小的结点

                    //二、将替代结点中的数据交给待删除结点(pDel)

                    //三、连接起来
                            /*(1)pDel为其双亲的左孩子
                            (2)pDel为其双亲的右孩子*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值