数据结构-查找-二叉排序查找

0、为什么需要二叉排序树

前面的查找我们都是静态查找,因为数据集是有序存放,查找的方法有多种,可以使用折半,插值,斐波那契等,但是因为有序,在插入和删除操作上的效率并不高。
这时我们就需要一种动态查找方法,既可以高效实现查找,又可以使得插入和删除效率不错,这时我们可以考虑二叉排序树

1、二叉排序树(Binary Sort Tree)

又称二叉查找树,它或者是一棵空树,或者是具有以下性质的二叉树:

1)若它的左子树不为空,则左子树上所有结点的值均小于它的根结构的值;

2)若它的右子树不为空,则右子树上所有结点的值均大于它的根结构的值;

3)它的左,右子树也分别为二叉排序树(递归)。

虽然我们得到的数据是无序的,但是我们按照二叉排序树的方式组织,中序遍历二叉树则是有序的。当然构造二叉排序树的目的更多的是未来方便查找,插入和删除关键字的速度。

1)查找:

/*
BiTree T    我们要搜索的二叉树
ElemType key我们要搜索的关键字
BiTree F    记录下我们的当前搜索子树的双亲结点
BiTree* P    当我们插入之前,会先搜索是否存在数据,若存在,不插入,若不存在,我们通过这个可以获取我们要插入的位置,直接插入即可
*/
Status SearchBST(BiTree T, ElemType key, BiTree F, BiTree* P)
{
    if (!T)
    {
        *P = F;        //若是未找到则返回父节点位置
        return FALSE;
    }
    else
    {
        if (T->data == key)
        {
            *P = T;    //若是找到则P返回该结点位置
            return TRUE;
        }
        else if (T->data < key)
            return SearchBST(T->rchild, key, T, P);
        else
            return SearchBST(T->lchild, key, T, P);
    }
}

2)插入

Status InsertBST(BiTree* T, int key)
{
    BiTree P,s;
    if (!T)
        return ERROR;
    if (!SearchBST(*T, key, NULL, &P))
    {
        //没有查找到有重复数据,获取到了应该插入的位置
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;
        s->lchild = s->rchild = NULL;
        if (!P)    //空树
            *T = s;
        else if (key < P->data)    //插入左子树
            P->lchild = s;
        else
            P->rchild = s;
        return OK;
    }
    else
        return ERROR;
}

3)删除

如果是叶子结点,则直接删除;

如果结点只存在左子树或右子树,则直接补上;

如果同时存在左子树和右子树,则按照中序遍历的顺序将删除结点的前驱或者后继补上即可;

Status Delete(BiTree* T)
{
    BiTree q,f;
    if (!*T)
        return ERROR;
    if (!(*T)->lchild)    //若是左子树不存在,我们只需要接到右子树
    {
        q = *T;
        *T = (*T)->rchild;
        free(q);
    }
    else if (!(*T)->rchild)    //若右子树不存在,接入左子树
    {
        q = *T;
        *T = (*T)->lchild;
        free(q);
    }
    else  //两边都存在,我们可以选择将右子树最小,或者左子树最大接入,这里选择右子树最小
    {
        f = *T;    //f指向q的双亲结点
        q = (*T)->rchild;
        while (q)
        {
            f = q;
            q = q->lchild;    //找到右子树最小,注意其可能存在右子树,我们要进行保存,接入其父节点
        }
        //将最小的数据更新到根节点处即可,然后记录最小点处,删除即可
        (*T)->data = q->data;
        if (f != (*T))
            f->lchild = q->rchild;
        else
            f->rchild = q->rchild;    //当右子树是一个右斜树
        free(q);
    }
    return TRUE;
}

Status DeleteBST(BiTree* T, int key)
{
    if (!*T)
        return ERROR;
    else
    {
        if ((*T)->data == key)    //找到了,开始删除
        {
            //删除该结点,由于要分情况讨论,所以另外写一个函数
        }
        else if ((*T)->data < key)
            DeleteBST(&(*T)->rchild, key);
        else
            DeleteBST(&(*T)->lchild, key);
    }
}

猜你喜欢

转载自www.cnblogs.com/lemonzhang/p/12396491.html