温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

《树》之伸展树

发布时间:2020-03-22 13:45:59 来源:网络 阅读:561 作者:Owefsad 栏目:开发技术

本文介绍什么?

  1. 使用伸展树有什么样的效果;

  2. 伸展树的定义;

  3. 伸展树ADT具体实现过程的描述;

  4. 代码实现。





一、使用伸展树(splay tree)的效果:

              使用伸展树时,对伸展树上任意一次操作的最坏运行时间为 O( N );但是,它保证了连续M次操作花费的最多时间为O(M ㏒N),从而可以推算出对伸展树的每一次操作的摊还时间为O( ㏒N)。




二、伸展树的定义:

        对于一颗二查查找树进行操作时,每访问一个节点,该节点都通过旋转操作被放到根上。这样的一颗二查查找树称为伸展树。




三、伸展树ADT的描述:

        1.伸展树的节点定义与二查查找树节点定义的方法一致,此处不再赘述;

        2.比起二查查找树,伸展树ADT只是对了一个旋转操作。在这里的旋转,我们称之为展开(Splaying)。设节点X为访问的节点,我们通过对节点X进行一系列操作,将节点X移动到根节点。

        3.节点X旋转的情况:

             ⑴节点X为根节点:什么都不做;

             ⑵节点X的父节点为根节点:

                     根节点的左子树=X的右子树;

                     X的右子树=根节点;

             ⑶节点X具有父节点(P)、祖父节点(G),此时有(两类)四种情况需要考虑:

                     ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;

                     ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;

                     ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;

                     ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;

        4.节点的删除:

              由于对节点X的每一次访问都需要将X移向根节点,所以懒惰删除在这里显得不太合适,在这里需要进行的直接删除。当进行删除操作时,首先需要访问节点X,节点X被移动到根节点,此时删除X花费的代价是比较小的。在删除节点X的时候,①访问X导致节点X被移向根节点,删除节点X并得到左、右两棵子树(TL、TR);②在右子树TR上访问最小节点Y(该节点一定没有左儿子),将Y移动到右子树的根节点;③令Y的左儿子为左子树TL。

        



四、核心代码实现:

    1.伸展树的伸展实现

         ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;

              操作:

                  G的左儿子=P的右儿子;

                  P的右儿子=G;

                  P的左儿子=X的右儿子;

                  X的右儿子=P;

//一字形(左左)

static Position ZigzigLL(Position g)
{
    Position p,x;
    p=g->left;x=p->left;
    
    g->left=p->right;
    p->right=g;
    p->left=x->right;
    x->right=p;
    
    return x;
}


ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;

        操作:

            G的右儿子=P的左儿子;

            P的左儿子=G;

            P的右儿子=X的左儿子;

            X的左儿子=P; 

//一字形(右右)

static Position ZigzigRR(Position g)
{
    Position p,x;
    p=g->right;x=p->right;
    
    g->right=p->left;
    p->left=g;
    p->right=x->left;
    x->left=p;
    
    return x;
}

           

ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;

        操作:

            G的左儿子=X的右儿子;

            X的右儿子=G;

            P的右儿子=X的左儿子;

            X的左儿子=P;

//一字形(左右)

static Position ZigzigLR(Position g)
{
    Position p,x;
    p=g->left;x=p->right;
    
    g->left=x->right;
    x->right=g;
    p->right=x->left;
    x->left=p;
    
    return x;
}


ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;           

        操作:

            G的右儿子=X的左儿子;

            X的左儿子=G;

            P的左儿子=X的右儿子;

            X的右儿子=P;

//一字形(右左)

static Position ZigzigRL(Position g)
{
    Position p,x;
    p=g->right;x=p->left;
    
    g->right=x->left;
    x->left=g;
    p->left=x->right;
    x->right=p;
    
    return x;
}


    3.伸展树的删除操作实现

//删除节点
void Delete(const ElementType x,const sTree st)
{
    if(NULL==st) printf("该树为空树\n");
    else{
        position temp=Find(x,st);
        Position root=FindMin(temp->right);
        root->left=temp->left;
        
        free(temp);
        temp=NULL;
        return ;
    }
}
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI