二叉查找树

二叉排序树又称为二叉查找树
递归定义:二叉排序树可以是空树,或具有如下性质:
1、若它的左子树非空,则左子树上所有的结点的值均小于根节点的值;
2、若它的右子树非空,则右子树上所有结点的值均大于或者等于根结点的值。
3、它的左右子树也分别为二叉排序/查找树
二叉排序树的存储结点为二叉树,使用二叉链表作为存储结构
!!二叉排序树的插入与创建
(1)二叉排序树的插入
算法思想:
1>.若二叉树是空树,则key成为二叉排序树的根。
2>.若二叉排序树非空,则将key与二叉排序树的跟进行比较:
    如果key的值等于根节点的值,则停止插入
    如果key的值小于根结点的值,则将key插入左子树
    如果key的值大于根结点的值,则将key插入到右子树
 
 二叉排序树的定义
 typedef struct node{
    int key;//关键字的值
    struct node *lchild,*rchild;
 }BSTNode,*BSTree;
 
 二叉排序树插入的递归算法
 void InsertBST(BSTree *bst,int key){
    BSTree s;
    if(*bst==NULL){//递归结束条件,空树,将key作为它的根
        s=(BSTree)malloc(sizeof(BSTNode)); //申请新的节点
        s->key=key;
        s->lchild=NULL;
        s->rchild=NULL;
        *bst=s;
    }
    else if(key<(*bst)->key)){ //将s插入到左子树
        InsertBST(&((*bst)->lchild),key);
    }
    else if(key>(*bst)->key)
        InsertBST(&((*bst)-rchild),key);
 }
 二叉排序树的插入算法的时间复杂度为O(log2n)。
 
 (2)二叉排序树的创建
算法思想:
先将二叉排序树初始化为一棵空树,然后逐个读入元素,每读一个元素创立一个新的结点,并插入到当前已经生成的二叉排序树中,即通过多次调用插入新节点的算法实现。注意:插入时比较结点顺序始终是从二叉树的根结点开始。
创建二叉排序树
void createBST(BSTree *bst){//从键盘输入元素的值,创建相应的二叉排序树
        int key;
        *bst=NULL;
        scanf("%d",&key);
        while(key!=ENDKEY){
                InsetBST(bst,key);
                scanf("%d",&key);
        
        }
}
假设有n个元素则需要插入n次,创建二叉排序树的时间复杂度为O(nlog2n)。

《3》二叉排序树的查找
因为二叉排序树可以看作是一个有序表,所以在二叉排序树上进行查找和折半查找类似
算法思想:
首先将待查关键字key与根结点关键字t进行比较,若:
    1、key=t,则返回根结点地址
    2、key<t,则进一步查找左子树
    3、key>t,则进一步查找右子树
递归算法:
    BSTree searchBST(BSTree bst,int key){
    //在指针bst所指二叉排序树中,递归查找某关键字等于key的元素,若查找成功,返回指向该元素结点指针,否则返回空指针
            if(bst)  return NULL;
            else if(bst->key==key)  return bst;
            else if(bst->key>key)   return searchBST(bst->lchild,key);//在左子树继续查找
            else return searchBST(bst->rchild,key);
    }
 非递归算法:
     BSTree searchBST(BSTree bst,int key){
     //在指针bst所指二叉排序树上查找关键字key的结点,若查找成功,返回指向该元素结点指针,否则返回空指针
            BSTree q;
            q=bst;
            while(q){
                if(q->key==key)   return q;
                if(q->key>key)    q=q->lchild;
                else q=q->rchild;
            }
            return NULL;//查找失败
     
     }
     

对于需要经常做插入、删除、查找运算的表,宜采用二叉排序树结构。
《4》二叉排序树的删除
从二叉排序树上删除一个结点,不能把以该结点为根的子树都删去,并且还需要保证删除后仍然保持二叉排序树的性质不变。所以说,在二叉排序树中删除一个结点相当于删去有序序列中的一个结点。
    算法思想:
    删除操作首先应该查找到该结点,看能否查找到,如果可以找到,假设要删除的结点为P,结点P的双亲结点为F,并假设结点P是结点F的左孩子(或者右孩子),则有:
    1>.若p为叶子结点,则可以直接删去。f->lchild=NULL;free(p);
    2>.若p结点只有左子树或者右子树,则可将p的左子树或者右子树,直接改为其双亲结点f的左子树。f->lchild=p->lchild;(或者f->lchild=p->rchild);free(p);
    3>.若p既有左子树又有右子树,则有两种方法:
        方法一:首先找到p结点在中序序列中的直接前驱s结点,然后将p的左子树改为f的左子树,将p的右子树改为s的右子树
        方法二:首先找到p结点在中序序列中的直接前驱s结点,然后用s结点的值替代p结点的值,再将s节点删除,原s结点的左子树改为s的双亲结点q的右子树
   BSTNode *DelBST(BSTree t,int key){
        BSTNode *p,*f,*s,*q;
        p=t;f=NULL;
        while(p){    //查找p结点过程
            if(p->key==key)  break;
            f=p;
            if(p->key>k)  p=p->lchild;
            else  p=p->rchild;
        }
        if(p=NULL) return t;//查找不到,返回原来的二叉排序树
        if(p->lchild==NULL){//当p没有左子树的时候
            if(f==NULL) t=p->rchild; //p是原二叉排序树的根
            else if(f->lchild==p)  //p是f的左孩子
                f->lchild=p->rchild;
            else  //p是f的右孩子
                f->rchild=p->rchild;
            free(p);
        }
        else {//p有右子树
            q=p;
            s=p->lchild;
            while(s->rchild){ //在p的左子树中查找最右下结点
                q=s;
                s=s->rchild;
            }
            if(q==p)
                q->lchild=s->child;//将s的左子树链到q上
            else
                q->rchild=s->lchild;
            p->key=s->key;
            free(s);
        
        }
     return t;
   }


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值