热门IT资讯网

《树》之伸展树

发表于:2024-11-24 作者:热门IT资讯网编辑
编辑最后更新 2024年11月24日,本文介绍什么?使用伸展树有什么样的效果;伸展树的定义;伸展树ADT具体实现过程的描述;代码实现。一、使用伸展树(splay tree)的效果:使用伸展树时,对伸展树上任意一次操作的最坏运行时间为 O(

本文介绍什么?

  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 ;    }}
0