C语言数据结构二叉排序树的建立、插入、删除、查找操作(原理+完整代码)

文章介绍了二叉查找树的基本原理,包括其左子树所有节点值小于根节点、右子树所有节点值大于根节点的特性。主要讨论了插入新节点、删除节点以及查找节点的算法,特别提到了删除节点的三种情况。此外,还提及了二叉查找树的时间复杂度及其在最坏情况下的性能问题,并提出AVL树作为改进方案。
摘要由CSDN通过智能技术生成

完整代码

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

typedef struct binode
{
    int data;
    struct binode *lchild,*rchild;
}BiTNode,*BiTree;

//查找函数
//f指向T的parent,查找成功p指向该结点;不成功,返回访问的最后一个结点
int searchBST(BiTree T,int key, BiTree f, BiTree *p)
{
    if(T==NULL)
    {
        *p= f;
        return 0;
    }
    else if(key == T->data)
    {
        *p=T;
        return 1;
    }
    else if(key < T ->data)
    {
        return searchBST(T->lchild, key, T,p);
    }
    else{
        return searchBST(T->rchild, key, T,p);
    }
}

//插入节点(创建树)
int insertBST(BiTree *T,int key)
{
    BiTree p,s;
    if(searchBST(*T,key,NULL,&p)==0)   //查找不成功,不存在相等的结点
    {
        s=(BiTree)malloc(sizeof(BiTNode));
        s->data=key;
        s->lchild=s->rchild=NULL;
        if(!p)
            *T=s;   //树为空,则s为根节点
        else if(key < p->data)
            p->lchild=s;
        else
            p->rchild=s;
        return 1;
    }
    else
        return 0;
}

//删除
int Delete(BiTree *p)
{
    BiTree q,s;
    if((*p)->rchild ==NULL)  //只有左子树
    {
        q=*p;
        *p=(*p)->lchild;
        free(q);
    }
    else if((*p)->lchild == NULL)   //只有右子树
    {
        q=*p;
        *p=(*p)->rchild;
        free(q);
    }
    else   //左右子树均不为空
    {
        q=*p;  s=(*p)->lchild;
        while (s->rchild)   //找到被删结点的左子树的最右结点
        {
            q=s; s=s->rchild;
        }
        (*p)->data = s->data;    //此时s为被删结点的左子树的最右结点
        if(q != *p)           //q为s 的父亲结点,此时q不重合p,也就是s不是p的右孩子
            q->rchild=s->lchild;
        else                         //此时q和p重合,s为p的右孩子
            q->lchild=s->lchild;
        free(s);
    }
    return 1;
}
//递归找到结点
int deleteBST(BiTree *T, int key)
{
    if(*T==NULL)
        return 0;
    else
    {
        if(key == (*T)->data)
        {
            Delete(T);
            return 1;
        }
        else if(key <(*T)->data)
            return deleteBST(&(*T)->lchild,key);
        else
            return deleteBST(&(*T)->rchild,key);
    }
}

void pre(BiTree T)
{
    if(T)
    {
        printf("%d ",T->data);
        pre(T->lchild);
        pre(T->rchild);
    }
}
int main()
{
    BiTree T=NULL;
    int a[15]={3,6,1,8,2,7,4,5,66};
    int i=0;
    while(a[i]!='\0')
    {
        insertBST(&T,a[i++]);
    }
    pre(T);
    printf("\n1.插入节点 2.删除结点\n");
    int f;int key;
    scanf("%d",&f);
    if(f==1)
    {
        printf("请输入插入的数字\n");
        scanf("%d",&key);
        insertBST(&T,key);
        pre(T);
    }
    else
    {
        printf("请输入删除的数字\n");
        scanf("%d",&key);
        deleteBST(&T,key);
        pre(T);
    }
    
    return 0;
}

二叉查找树的原理

1、若左子树不为空,左子树上所有节点值小于 它根节点的值
2、若右子树不为空,右子树上所有节点值大于 它根节点的值
3、每个节点的左右子树也是二叉排序树

目的:提高查找、插入、删除关键字的速度(不是为了排序)
时间复杂度:由于查找性能取决于树的形态,所以在O(log2n)(二叉树的平均高度)~ O(n) (最坏情况:单链表)之间。
二叉排序树的深度、性能不稳定
改进:AVL树(不断的修改树的形态) 链接: 二叉平衡树(AVL树)

插入

查找不成功(不重复) -> 插入

删除

分为三种情况:
(1)为叶子结点 :直接删除
(2)无左、右子树:删除结点,接上孩子即可
(3)左、右子树都有:找需要删除结点的左子树的最右结点(或右子树的最左结点)替换此节点。因为左子树的最右结点和右子树的最左结点最接近根节点,所以用它替换。再把此节点的右或左子树接到此节点的父亲结点上。

查找

通过递归的方式比较找到结点
查找需要为插入做准备,因此函数变量里有个指针。

参考资料:《大话数据结构》
如果文章有问题,请给我留言哦,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yyzuimei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值