二叉排序数

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

#define TRUE 1
#define FALSE 0
#define ElemType int
#define KeyType int


/* 二叉排序树的节点结构定义 */
typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;


/*二叉排序树查找算法*/
int SearchBST(BiTree T, KeyType key, BiTree f, BiTree *p)
{
    //如果 T 指针为空,说明查找失败,令 p 指针指向查找过程中最后一个叶子结点,并返回查找失败的信息
    if(!T)
    {
        *p = f;
        return FALSE;
    }
    //如果相等,令 p 指针指向该关键字,并返回查找成功信息
    else if (key == T->data)
    {
        *p = T;
        return TRUE;
    }
    //如果 key 值比 T 根结点的值小,则查找其左子树
    else if (key < T->data)
    {
        return SearchBST(T->lchild, key, T, p);
    }
    //如果 key 值比 T 根结点的值大,则查找其右子树
    else
    {
        return SearchBST(T->rchild, key, T, p);
    }
}


int InsertBST(BiTree *T, ElemType e)
{
    BiTree p = NULL;
    //如果查找不成功,需做插入操作
    if (!SearchBST((*T), e, NULL, &p))
    {
        //初始化插入结点
        BiTree s = (BiTree)malloc(sizeof(BiTNode));
        s->data = e;
        s->lchild = s->rchild = NULL;

        //如果 p 为NULL,说明该二叉排序树为空树,此时插入的结点为整棵树的根结点
        if (!p)
        {
            *T = s;
        }

        //如果 p 不为 NULL,则 p 指向的为查找失败的最后一个叶子结点,只需要通过比较 p 和 e 的值确定 s 到底是 p 的左孩子还是右孩子
        else if (e < p->data)
        {
            p->lchild = s;
        }
        else
        {
            p->rchild = s;
        }

        return TRUE;
    }

    //如果查找成功,不需要做插入操作,插入失败
    return FALSE;
}

//删除函数
int Delete(BiTree *p)
{
    BiTree q, s;
    //情况 1,结点 p 本身为叶子结点,直接删除即可
    if (!(*p)->lchild && !(*p)->rchild)
    {
        *p = NULL;
    }

    else if (!(*p)->lchild)   //左子树为空,只需用结点 p 的右子树根结点代替结点 p 即可;
    {
        q = *p;
        *p = (*p)->rchild;
        free(q);
    }

    else if (!(*p)->rchild)  //右子树为空,只需用结点 p 的左子树根结点代替结点 p 即可;
    {
        q = *p;
        *p = (*p)->lchild;//这里不是指针 *p 指向左子树,而是将左子树存储的结点的地址赋值给指针变量 p
        free(q);
    }

    else  //左右子树均不为空,采用直接前驱来代替需要删除的结点
    {
        q = *p;
        s = (*p)->lchild;
        //遍历,找到结点 p 的直接前驱
        while (s->rchild)
        {
            q = s;
            s = s->rchild;
        }

        //直接改变结点 p 的值
        (*p)->data = s->data;

        //判断结点 p 的左子树 s 是否有右子树,分为两种情况讨论
        if (q != *p)
        {
            q->rchild = s->lchild;//若有,则在删除直接前驱结点的同时,令前驱的左孩子结点改为 q 指向结点的孩子结点
        }
        else
        {
            q->lchild = s->lchild;//否则,直接将左子树上移即可
        }
        free(s);
    }
    return TRUE;
}

int DeleteBST(BiTree *T, int key)
{
    if (!(*T))  //不存在关键字等于key的数据元素
    {
        return FALSE;
    }
    else
    {
        if (key == (*T)->data)
        {
            Delete(T);
            return TRUE;
        }
        else if (key < (*T)->data)
        {
            //使用递归的方式
            return DeleteBST(&(*T)->lchild, key);
        }
        else
        {
            return DeleteBST(&(*T)->rchild, key);
        }
    }
}


void order(BiTree t)//中序输出
{
    if (t == NULL)
    {
        return;
    }
    order(t->lchild);
    printf("%d ", t->data);
    order(t->rchild);
}


int main()
{
    while(1)
    {
        BiTree T = NULL;

        printf("你想在无序序列中输入几个元素用来构建一棵二叉排序树?\n");
        int n;
        scanf("%d", &n);

        //创建二叉排序数
        for(int i=0; i<n ; i++)
        {
            printf("请输入这个无序序列中的元素:");
            int x;
            scanf("%d", &x);
            InsertBST(&T, x);
        }

        //中序输出二叉排序树
        printf("中序遍历二叉排序树:\n");
        order(T);
        printf("\n");

        //删除操作
        printf("请输入您想要删除的元素:\n");
        int x1;
        scanf("%d", &x1);
        DeleteBST(&T, x1);
        if(DeleteBST(&T, x1))
        {
            printf("删除3后,中序遍历二叉排序树:\n");
            order(T);
            printf("\n");
        }
        else
        {
            printf("请输入正确的关键字!\n");
        }
        printf("-------------------------------------\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值