二叉搜索树的创建,删除,查找

二叉搜索树的概念

  二叉搜索树又称二叉排序树,它或者是一颗空树,或者是具有以下性质的二叉树

  • 若它的左子树不为空,则左子树上的所有结点的值都小于根结点的值。
  • 若它的右子树不为空,则右子树上的所有结点的值都大于根节点的值。
  • 它的左右子树也分别为二叉搜索树。
    《二叉搜索树的创建,删除,查找》
二叉搜索树的操作

  查找关键字data:①.若根节点为空,即二叉搜索树为空。返回0。
②.若data>根节点的data,在其右子树查找;若data<根节点的data,在其左子树查找;若data==根节点的data,返回1;找不到返回0。

int  FindBSTree(BSTree *BStree, BSDataType data)
{
    BSTree *cur = BStree;
    //根节点为空,即二叉树为空,返回0
    if (BStree == NULL)
    {
        return 0;
    }
    while (cur != NULL)
    {
        if (cur->_data == data)
        {
            return 1;
        }
        else if (cur->_data > data)
        {
            cur = cur->_pleft;
        }
        else
            cur = cur->_pright;
    }
    //cur==NULL即没有找到元素和data相等,返回0
    return 0;
}

  递归查找

//递归查找
int  FindBSTree(BSTree *BStree, BSDataType data)
{
    BSTree *cur = BStree;
    if (BStree == NULL)
    {
        return 0;
    }
    if (cur->_data == data)
    {
        return 1;
    }
    else if (cur->_data > data)   
    {
        return FindBSTree(BStree->_pleft,data);
    }
    else
    {
        return FindBSTree(BStree->_pright, data);
    }
}

  插入元素data:在二叉树中插入元素时,必须检测该元素在树中是否已经存在,若存在则不进行插入。
①.树为空,即二叉树为空时直接插入。
②.树不为空,若data>根节点的data,在右子树插入;若data<根节点的data,在其左子树插入;若data==根节点的data,返回0,不插入;
在找要插入的位置的时候始终记录双亲结点。
③.找到要插入的位置之后,判断双亲结点的data和要插入的data的大小,若data>双亲结点的data,则插入右子树,否则插入左子树。

//插入
int InsertBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *cur  = NULL;
    BSTree *parent = NULL;
    assert(BStree);
    cur = *BStree;
    //1.若二叉树为空
    if (NULL == *BStree)    
    {
        *BStree = BuyNode(data);
    }
    //2.若二叉树不为空 
    else
    {
        //①.寻找插入的位置
        while (cur != NULL)
        {
            parent = cur;
            if (data < cur->_data)
            {         
                cur = cur->_pleft;
            }
            else if (data > cur->_data)
            {
                cur = cur->_pright;
            }
            else
            {
                return 0;
            }
        }
        //②.建立新结点
        cur = BuyNode(data);
        //③.data若比双亲大,则插右边,若比双亲小,则插左边
        if (data < parent->_data)
        {
            parent->_pleft = cur;
        }
        else
        {
            parent->_pright = cur;
        }
    }
    return 1;
}

  递归插入:

int InsertBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *cur = NULL;
    BSTree *parent = NULL;
    assert(BStree);
    cur = *BStree;
    if (NULL == *BStree)
    {
        *BStree = BuyNode(data);
    }
    else
    {
        if (data > cur->_data)
        {
            return InsertBSTree(&(*BStree)->_pright, data);
        }
        else if (data < cur->_data)
        {
            return  InsertBSTree(&(*BStree)->_pleft, data);
        }
        else
        {
            return 0;
        }
    }
    return 1;
}

  删除元素data:在二叉树中删除元素时,必须检测该元素在树中是否已经存在,若不存在则直接返回0,不删除。若存在又分为以下四种情况:

  1. 要删除的结点无孩子结点(叶子结点)。
  2. 要删除的结点只有右孩子结点。
  3. 要删除的结点只有左孩子结点。
  4. 要删除的结点有左,右孩子结点。
    情况1可以和情况2或者情况3合并,对于上述情况,相应的删除方法有:
    ① 直接删除该结点
    ② 删除该结点且被删除结点的双亲结点指向被删除孩子的右孩子结点。
    ③ 删除该结点且被删除结点的双亲结点指向被删除孩子的左孩子结点。
    ④ 在它的右子树中寻找最小的结点,用它的值替换被删除结点的值。
int  DeleteBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *cur = NULL;
    BSTree *del = NULL;      //要删除的结点
    BSTree *parent = NULL;   //要删除结点的双亲结点
    assert(BStree);
    cur = *BStree;
    if (*BStree == NULL)
    {
        return 0;
    }
    //寻找要删除的点
    while (cur != NULL)
    {
        if (cur->_data == data)
        {
            break;
        }
        else if (data < cur->_data)
        {
            parent = cur;
            cur = cur->_pleft;
        }
        else
        {
            parent = cur;
            cur = cur->_pright;
        }
    }
    if (cur == NULL)
    {
        //证明要删除的元素不在二叉搜索树内
        return 0;
    }
    //只有右孩子或者叶子
    if (cur->_pleft == NULL)
    {
        //如果是根节点,让根节点指向它的右子树
        if (cur == *BStree)
        {
            *BStree = (*BStree)->_pright;
        }
        else
        {
            //判断cur是双亲的左孩子还是右孩子
            //双亲指向cur的右孩子,因为左孩子为空
            if (parent->_pleft == cur)
            {
                parent->_pleft = cur->_pright;
            }
            else
            {
                parent->_pright = cur->_pright;
            }
        }
    }
    //只有左孩子
    else if (cur->_pright == NULL)
    {
        //如果是根节点,让根节点指向它的左子树
        if (cur == *BStree)
        {
            *BStree = (*BStree)->_pleft;
        }
        else
        {
            //判断cur是双亲的左孩子还是右孩子
            //双亲指向cur的左孩子,因为右孩子为空
            if (parent->_pleft == cur)
            {
                parent->_pleft = cur->_pleft;
            }
            else
            {
                parent->_pright = cur->_pleft;
            }

        }
    }
    //左右孩子均存在
    else
    {
        del = cur->_pright;
        parent = cur;
        //找到右子树里面最小的一个,覆盖要删除的结点
        while (del->_pleft)
        {
            parent = del;
            del = del->_pleft;
        }
        //将找到的结点的值赋给要删除的结点
        cur->_data = del->_data;
        //删除replace 
        if (parent->_pleft == del)
        {
            parent->_pleft = NULL;
            cur = del;
        }
        else
        {
            parent->_pright = NULL;
            cur = del;
        }
    }
    free(cur);
    cur = NULL;
    return 1;
} 

  递归删除

int DeleteBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *del = NULL;
    BSTree *cur = NULL;

    assert(BStree);
    if ((*BStree) == NULL)
    {
        return 0;
    }
    if (data < (*BStree)->_data )
    {
        return DeleteBSTree(&(*BStree)->_pleft,data);
    }
    else if (data > (*BStree)->_data )
    {
        return DeleteBSTree(&(*BStree)->_pright, data);
    }
    else
    {
        cur = *BStree;
        if ((*BStree)->_pleft == NULL)
        {
            *BStree = (*BStree)->_pright;
            free(cur);
            cur = NULL;
        }
        else if ((*BStree)->_pright == NULL)
        {
            *BStree = (*BStree)->_pleft;
            free(cur);
            cur = NULL;
        }
        else
        {
            del = (*BStree)->_pright;
            while (del->_pleft) 
            {
                del = del->_pleft;
            }
            (*BStree)->_data = del->_data;
            return DeleteBSTree(&(*BStree)->_pright, del->_data);
        }
    }
    return 1;
}
                       整体代码:

.h文件

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

//二叉树的结构
typedef int BSDataType;
typedef struct BSTree
{
    struct BSTree *_pleft;
    struct BSTree *_pright;
    BSDataType _data;
}BSTree;
//初始化
void InitBSTree(BSTree **BSTree);
//插入
int InsertBSTree(BSTree **BSTree, BSDataType data);
//中序遍历
void InOrder(BSTree *BStree);
//删除
int DeleteBSTree(BSTree **BStree, BSDataType data);
//查找
int  FindBSTree(BSTree *BStree, BSDataType data);
//销毁
void DestroyBSTree(BSTree **BStree);

.c文件

#include"BSTree.h"


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


BSTree* BuyNode(BSDataType d)
{
    BSTree *newnode = (BSTree *)malloc(sizeof(BSTree));
    if (NULL == newnode)
    {
        //若开辟空间失败,则打印出错误,不进行后面的代码
        assert(0);
        return NULL;
    }
    newnode->_data = d;
    newnode->_pleft = NULL;
    newnode->_pright = NULL;

    return newnode;
}
////插入
//int InsertBSTree(BSTree **BStree, BSDataType data)
//{
// BSTree *cur = NULL;
// BSTree *parent = NULL;
//
// assert(BStree);
// cur = *BStree;
// //1.若二叉树为空
// if (NULL == *BStree) 
// {
// *BStree = BuyNode(data);
// }
// //2.若二叉树不为空 
// else
// {
// 
// //①.寻找插入的位置
// while (cur != NULL)
// {
// parent = cur;
// if (data < cur->_data)
// { 
// cur = cur->_pleft;
// }
// else if (data > cur->_data)
// {
// cur = cur->_pright;
// }
// else
// {
// return 0;
// }
// }
// //②.建立新结点
// cur = BuyNode(data);
// //③.data若比双亲大,则插右边,若比双亲小,则插左边
// if (data < parent->_data)
// {
// parent->_pleft = cur;
// }
// else
// {
// parent->_pright = cur;
// }
// }
// return 1;
//}
//递归插入
int InsertBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *cur = NULL;
    BSTree *parent = NULL;
    assert(BStree);
    cur = *BStree;
    if (NULL == *BStree)
    {
        *BStree = BuyNode(data);
    }
    else
    {
        if (data > cur->_data)
        {
            InsertBSTree(&(*BStree)->_pright, data);
        }
        else if (data < cur->_data)
        {
            InsertBSTree(&(*BStree)->_pleft, data);
        }
        else
        {
            return 0;
        }
    }
    return 1;
}
//中序遍历 左-->根-->右
void InOrder(BSTree *BStree)
{
    if (BStree == NULL)
    {
        return;
    }
    InOrder(BStree->_pleft);
    printf("%d ", BStree->_data);
    InOrder(BStree->_pright);
}



////删除
//int DeleteBSTree(BSTree **BStree, BSDataType data)
//{
// BSTree *cur = NULL;
// BSTree *del = NULL; //要删除的结点
// BSTree *parent = NULL; //要删除结点的双亲结点
// assert(BStree);
// cur = *BStree;
// if (*BStree == NULL)
// {
// return 0;
// }
// //寻找要删除的点
// while (cur != NULL)
// {
// if (cur->_data == data)
// {
// break;
// }
// else if (data < cur->_data)
// {
// parent = cur;
// cur = cur->_pleft;
// }
// else
// {
// parent = cur;
// cur = cur->_pright;
// }
// }
// if (cur == NULL)
// {
// //证明要删除的元素不在二叉搜索树内
// return 0;
// }
// //只有右孩子或者叶子
// if (cur->_pleft == NULL)
// {
// //如果是根节点,让根节点指向它的右子树
// if (cur == *BStree)
// {
// *BStree = (*BStree)->_pright;
// }
// else
// {
// //判断cur是双亲的左孩子还是右孩子
// if (parent->_pleft == cur)
// {
// parent->_pleft = cur->_pright;
// }
// else
// {
// parent->_pright = cur->_pright;
// }
// }
// }
// //只有左孩子
// else if (cur->_pright == NULL)
// {
// //如果是根节点,让根节点指向它的左子树
// if (cur == *BStree)
// {
// *BStree = (*BStree)->_pleft;
// }
// else
// {
// //判断cur是双亲的左孩子还是右孩子
// if (parent->_pleft == cur)
// {
// parent->_pleft = cur->_pleft;
// }
// else
// {
// parent->_pright = cur->_pleft;
// }
//
// }
// }
// //左右孩子均存在
// else
// {
// del = cur->_pright;
// parent = cur;
// //找到右子树里面最小的一个
// while (del->_pleft)
// {
// parent = del;
// del = del->_pleft;
// }
// //将找到的结点的值赋给要删除的结点
// cur->_data = del->_data;
// //删除replace 
// if (parent->_pleft == del)
// {
// parent->_pleft = NULL;
// cur = del;
// }
// else
// {
// parent->_pright = NULL;
// cur = del;
// }
// }
// free(cur);
// cur = NULL;
// return 1;
//} 


//递归删除
int DeleteBSTree(BSTree **BStree, BSDataType data)
{
    BSTree *del = NULL;
    BSTree *cur = NULL;

    assert(BStree);
    if ((*BStree) == NULL)
    {
        return 0;
    }
    if (data < (*BStree)->_data )
    {
        DeleteBSTree(&(*BStree)->_pleft,data);
    }
    else if (data > (*BStree)->_data )
    {
        DeleteBSTree(&(*BStree)->_pright, data);
    }
    else
    {
        cur = *BStree;
        if ((*BStree)->_pleft == NULL)
        {
            *BStree = (*BStree)->_pright;
            free(cur);
            cur = NULL;
        }
        else if ((*BStree)->_pright == NULL)
        {
            *BStree = (*BStree)->_pleft;
            free(cur);
            cur = NULL;
        }
        else
        {
            del = (*BStree)->_pright;
            while (del->_pleft) 
            {
                del = del->_pleft;
            }
            (*BStree)->_data = del->_data;
            DeleteBSTree(&(*BStree)->_pright, del->_data);
        }
    }
    return 1;
}
//查找
int  FindBSTree(BSTree *BStree, BSDataType data)
{
    BSTree *cur = BStree;
    //根节点为空,即二叉树为空,返回0
    if (BStree == NULL)
    {
        return 0;
    }
    while (cur != NULL)
    {
        if (cur->_data == data)
        {
            return 1;
        }
        else if (cur->_data > data)
        {
            cur = cur->_pleft;
        }
        else
            cur = cur->_pright;
    }
    //cur==NULL即没有找到元素和data相等,返回0
    return 0;
}

////递归查找
//int FindBSTree(BSTree *BStree, BSDataType data)
//{
// BSTree *cur = BStree;
// if (BStree == NULL)
// {
// return 0;
// }
// if (cur->_data == data)
// {
// return 1;
// }
// else if (cur->_data > data) 
// {
// return FindBSTree(BStree->_pleft,data);
// }
// else
// {
// return FindBSTree(BStree->_pright, data);
// }
//}

//销毁二叉树
void DestroyBSTree(BSTree **BStree)
{
    assert(BStree);
    if (*BStree == NULL)
    {
        return;
    }
    DestroyBSTree(&(*BStree)->_pleft);
    DestroyBSTree(&(*BStree)->_pright);
    free(*BStree);
    *BStree = NULL;
}

测试文件:

#include"BSTree.h"

void TestBSTree()
{
    BSTree *BStree;
    int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 };
    int i = 0;
    //初始化二叉搜索树
    InitBSTree(&BStree);
    for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
    {
        //插入
        InsertBSTree(&BStree, a[i]);
    }
    //插入
    InsertBSTree(&BStree, 10);
    //中序遍历
    InOrder(BStree);
    printf("\n");
    //查找
    if (FindBSTree(BStree, 1))
    {
        printf("找到了!\n");
    }
    else
    {
        printf("没找到!\n");
    }
    //查找
    if (FindBSTree(BStree, -1))
    {
        printf("找到了!\n");
    }
    else
    {
        printf("没找到!\n");
    }
    //删除
    DeleteBSTree(&BStree, 5);
    //删除
    DeleteBSTree(&BStree, 3);
    //中序遍历
    InOrder(BStree);
    printf("\n");
    //摧毁
    DestroyBSTree(&BStree);
}

int main()
{
    TestBSTree();
    system("pause");
    return 0;
}

《二叉搜索树的创建,删除,查找》

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