二叉排序树

二叉排序树或者是空树,或者是具有系列性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值均小于他的根结点的值
若它的右子树不空,则右子树所有结点的值均大
于它的根节点
它的左右子数也分别为二叉排序树
目的:提高查找和插入删除关键字的速度

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

#define FALSE 0
#define TRUE 1

//二叉树的二叉链表节点结构定义
typedef struct BiTNode
{
    int data;

    struct BiTNode *lchild,*rchild;//定义左孩子,右孩子
}BiTNode,*BiTree;


int SearchBST(BiTree T, int key,BiTree f,BiTree *p)//T:代表这棵树;key:需要查找的值; f:用来保存当前结点的双亲;p:用来保存查找元素的结点
{
    if(!T) //查找不到该元素或者这棵树为空
    {
        *p = f;//如果查找不到该key,将p指向路径上最后一个访问的结点,并返回FLASE
    return FALSE;
    }
    else if(key == T->data)//如果当前结点的数据等于要查找数据key,将数据结点保存到p中,并返回TRUE
    {
        *p = T;

    return TRUE;
    }
    else if(key < T->data)//如果key小于当前结点的数据,则进行左子树的递归查询
    {
        return SearchBST(T->lchild,key,T,p);
    }
    else               //如果key大于当前结点的数据,则进行右子树的递归查询
    {
        return SearchBST(T->rchild,key,T,p);
    }
}

int InsertBST(BiTree *T, int key)
{
    BiTree p,s;

    if(!SearchBST(*T,key,NULL,&p))//在插入数据之前,首先检查该树中是否已经插入该数据
    {
        s = (BiTree)malloc(sizeof(BiTree));
    s ->data = key;
    s->lchild = s->rchild = NULL;

    if(!p) //如果该树为空树
    {
        *T = s; //插入s为新的根结点
    }
    else if(key < p->data)//该树不是空树且插入的值小于p结点上的数据
    {                     //将s插入为p的左孩子结点
        p->lchild = s;
    }
    else //插入的值大于p结点上的数据,将s插入为p的右孩子结点
    {
        p->rchild = s;
    }

    return TRUE;
    }
    else //如果该树中已经有这个key,则不进行插入操作
    {
        return FALSE;
    }
}

void CreateBST(BiTree *T,int *key,int n) //创建一棵二叉排序树
{
    int i;

    *T = NULL; 

    for(i = 0; i < n; ++i) //迭代插入结点数据
    {
        InsertBST(T,key[i]);
    }
}

void inorder(BiTree p) //中序遍历
{
    if(p != NULL)
    {
        inorder(p->lchild);//先遍历左孩子,打印左孩子结点数据

    printf("%d ",p->data);

    inorder(p->rchild);//最后遍历右孩子,打印右孩子节点数据
    }
}

int DeleteBST(BiTree *T,int key)
{
    if(! *T)//如果这棵树为空,那么直接结束程序
    {
       return FALSE;
    }
    else
    {
        if(key == (*T)->data)//如果要删除的数据是根结点的数据,单独进行Delete操作
    {
        return Delete(T);
    }
    else if(key < (*T)->data)//如果要删除的数据小于当前结点的数据,那么就在当前结点的左子树里面进行查找删除操作,这里用的也是递归
    {
        return DeleteBST(&(*T)->lchild,key);//lchild是指针,传参的时候取地址
    }
    else//如果要删除的数据大于当前结点的数据,那么就在当前结点的右子树里面进行查找删除操作
    {
        return DeleteBST(&(*T)->rchild,key);
    }

    }


}

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; //q指向结点双亲,寻找到最右数据时需要将最右结点的左子树接到双亲结点的右子树上

        s = s->rchild;
    }

    (*p)->data = s->data;//替换数据,被删除的结点的关系并没有被替换

    if( q != *p) //被删除的结点下的左子树有右子树
    {
        q->rchild = s->lchild;
    }
    else//被删除的结点下的左子树没有右子树
    {
        q->lchild = s->lchild;
    }

    free(s);
    }

    return TRUE;
}


int main()
{
    int i;

    int num = 10;

    int key[num];

    BiTree T = NULL;

    printf("please input the num\n");

    for(i = 0; i < num; i++ )
    {
        scanf("%d",&key[i]);
    }

    CreateBST(&T,key,10);

    inorder(T);

    DeleteBST(&T,5);


    inorder(T);
    return 0;
}

程序参考《大话数据结构》
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值