16 - 12 - 11 二叉排序树

二叉排序树:( BST : Binary_Sort_Tree )
设查找的数据集是普通的顺序存储,那么插入操作就是将记录放在表的末端,给表记录数加一即可,删除操作可以删除后,后面的记录向前移,也可以是要删除的元素与最后一个元素互换,表记录数减一,反正整个数据集也没有什么顺序,这样的效率也不错。应该说,插入和删除对于顺序存储结构来说,效率是可以接受的,但是这样的表由于无序造成查找的效率很低 如果查找的数据集是有序线性表,并且是顺序存储的,查找可以用折半、插值、斐波那契等查找算法来实现,可惜因为有序,在插入和删除操作上,就需要耗费大量的时间。有没有一种即可以使得插入和删除效率不错,又可以比高效率地实现查找的算法呢?

这里写图片描述

二叉排序树的查找要在一开始就建立一个排序树的存储结构。

/*查找,注意二重指针的巧妙利用*/
typedef struct Binary
{
    int data;
    struct Binary *lchild,*rchild
}BiTNode,*BiTree;

Status SearchBST(BiTree T,int key,BiTree f,BiTree *p)  
{                                       //p是二重指针
    if(!T){
        *p = f;
        return FALSE;
    }else if(key == T->data){
        *p = T;
        return TRUE;
    }else if(key < T->data){  //在左边找咯
        return SearchBST(T->lchild,key,T,p);
    }else{   //key > T->data,在右边找
        return SearchBST(T->rchild,key,T,p);
    }
}
/*当不存在这个 key 时,怒插一个在里面(手动滑稽)*/
Status  InsertBST(BiTree T,int key)
{
    BiTree p,s;
    if( !SearchBST(*T, key, NULL, &p) )  //1、        
    {
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;
        s->lchild = s->rchild = NULL;
        if(!p){   //!p说明树不存在。。
            *T= s;    //插入s为新的根节点
        }else if(key < p->data)  //p有所指
            p->lchild = s;
        else //(key > p->data)
            p->rchild = s;
        return TRUE;
    }
    else
        return FALSE;
}
//1、 因为p是二重指针,所以在内存里保存下来。
    //search函数返回false时,if成立,说明要么这是个空树,
    //要么因为最终到达树底也没找到该节点。比如你想找 9 这个
    //节点,树中有一个叶节点8,那么下一步递归就去寻找8的
    //右子树,8哪来的右子树?!自然递归过去的T->xchild为空
    //进入if语句后,因为p = *T,若p不存在说明不存在树,
    //然后巴拉巴拉~~~

/*创建一个已知节点的树~~~*/
int i;
int a[10] = {62,88,58,47,35,73,51,99,37,93};
BiTree T = NULL;
for(i = 0; i < 10 ; i++ )
{
    InsertBST(&T,a[i]);  //哈哈
}

/*删除较麻烦,保持二叉排序树不能从中间断掉,所以分类讨论*/
//1、一是删除叶子结点,很容易
//2、而是删除只有左子树或只有右子树的节点,相对也比较好解决,
//只需要将整个左右子树进行移动和删除即可,
Status DeleteBST(BiTree *T,int key) //查找到key后删除
{
    if(!*T)
        return FALSE;
    else{
        if(key == (*T)->data)
            return Delete(T);  //delete在下面
        else if(key < (*T)->data))
            return DeleteBST(&(*T)->lchild,key) //key比较小,那一定在左边~
        else
            return DeleteBST(&(*T)->rchild,key) 
    }
}
Status 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;  //37覆盖47
        if(q != *p)   //1、
            q->rchild = s->lchild;  //重接 q 的右子树
        else
            q->lchild = s->lchild;  //重接 q 的右子树
        free(s);
    }   
    return TRUE;
}
//1、注意!q = *p的情况是:(*p)->lchild 没有左子树~


// ————-《大话数据结构》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值