【数据结构】——二叉排序树

上一篇文章,我们详细的讲述了在线性表中一个比较常用且高效的查找算法——折半查找,但是如果是遇到了要将数据进行插入和删除时的动态查找表我们又应该如何来实现呢?
由此引出了二叉排序树的概念,它既可以使得插入和删除效率不错,又可以比较高效率的实现查找,这篇文章就来好好认识一下他吧~

一、什么是二叉排序树

二叉排序树又称二叉查找树,它或是一颗空树,或者具有下列性质的二叉树:

  • 若他的左子树不为空,则左子树上所有结点的值均小于它根结点的值
  • 若他的右子树不空,则右子树上所有结点的值均大于他的根结点的值
  • 他的左右子树也分别为二叉排序树
    如图:
    在这里插入图片描述
    目的:为了提高查找和插入删除关键字的速度。

二、二叉排序树的查找操作

首先,提供一个二叉树的结构

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

二叉排序树查找的实现

//指针f指向T的双亲,其初始调用值为NULL
//若查找成功,则指针p指向该数据元素结点,并返回TRUE
//否则指针p指向查找路径上访问的最后一个结点并返回false
Status SearchBST(BiTree T,int key,BiTree f,BiTree *P)
{
    if(!T)
    {
        *p = f;
        return fales;
    }
    else if( key == T->data)
    {
        *p =T;
        return true;
    }
    else if(key < T>data)
        return SearchBST(T>lchid,key,T,p);//在左子树继续查找
    else
        return SearchBST(T>rchid,key,T,p);//在右子树继续查找
}

算法分析:
SearchBST函数是一个可递归运行的函数,f指向T的双亲,当T指向根结点的时候,f的初值就为NULL。

三、二叉树的插入操作

Status InsertBST(BiTree *T,int key)
{
    BiTree p,s;
    if(!SearchBST(*T,key,ULL,&p))//如果查找不成功
    {
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;
        s->lchild = s->rchild = NULL;
        if(!p)
            *T = s;//插入s为新的根结点
        else if(key < p->data)
            p->lchid = s;//插入s为左孩子
        else
            p->rchild = s;
    }
    else
        return false;
}

有了上述的插入操作,我们就可以利用其创建一颗二叉树了

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、删除的结点只有左子树或只有右子树的情况:删除结点过后将他的左子树或右子树整个移动到删除结点的位置即可。
在这里插入图片描述

3、删除的结点既有左子树又有右子树:找到要删除结点p的直接去前驱(或直接后继)s,用s来替换节点p,然后再删除此节点s

代码实现:
先在二叉树中查找到要删除的结点

Status DeleteBST(BiTree *T,int key)
{
    if(!*T)//不存在关键字为key的数据元素
        return false;
    else
    {
        if(key == (*T)->data)
            return Delete(T);
        else if(key < (*T)->data)
            return DeleteBST(&(*T)->lchid,key);
         else
            return DeleteBST(&(*T)->lchid,key);
     }
 }

Delete函数的实现

Status Delete(BiTree* p)
{
    BiTree q,s;
    if((*p)->rchild = NULL)//右子树空则需重接他的左子树
    {
        q = *p;
        *p = (*p)->lchid;
        free(q);
    }
    else if((*p)->lchild = NULL)//左子树空则需重接他的右子树
    {
        q = *p;
        *p = (*p)->rchid;
        free(q);
    }
    else//左右子树均不空
    {
        q = *p;
        s = (*p)->lchid;
        while(s->rchild)
        {
            q=s;
            s=s->child;
        }//q始终是s走过的上一个结点位置
        (*p)->data = s->data;
        if(q != *p)
            q->rchild = s->lchid;
        else
            q->lchid = s->lchid;
        free(s);
    }
    return ture;
}

过程分析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了62 篇原创文章 · 获赞 7 · 访问量 2577

猜你喜欢

转载自blog.csdn.net/qq_43412060/article/details/104397579