《树》之伸展树

本文介绍什么?

  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 ;
    }
}
时间: 2024-10-12 16:41:16

《树》之伸展树的相关文章

poj_3580 伸展树

自己伸展树做的第一个题 poj 3580 supermemo. 题目大意 对一个数组进行维护,包含如下几个操作: ADD x, y, d 在 A[x]--A[y] 中的每个数都增加d REVERSE x, y 将 A[x]--A[y] 中的数进行反转,变为 A[y],A[y-1]....A[x+1],A[x] REVOLVE x, y, T 将 A[x]--A[y]中的数连续右移T次 INSERT x, P 在A后添加数P DELETE x 删除A[x] MIN x, y 查询A[x]--A[y

树-伸展树(Splay Tree)

伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二叉查找树,即它具有和二叉查找树一样的性质:假设x为树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x].如果y是x的左子树中的一个结点,则key[y] <= key[x]:如果y是x的右子树的一个结点,则key[y] >= key[x]. (02) 除了拥有二叉查找树的性质

Splay Tree(伸展树)

参考:<数据结构(C++语言版)>邓俊辉著 (好书 一. 伸展树(由 D. D. Sleator 和 R. E. Tarjan 于 1985 年发明)也是平衡二叉搜索树的一种形式.相对于 AVL 树,伸展树的实现更为简洁 伸展树无需时刻都严格地保持全树的平衡,但却能够在任何足够长的真实操作序列中,保持分摊意义上的高效率 伸展树也不需要对基本的二叉树节点结构做任何附加的要求或改动,更不需要记录平衡因子或高度之类的额外信息,故适用范围更广 二.局部性 信息处理的典型模式是,将所有的数据项视作一个集

伸展树、B树与B+树

B树 如果数据装不下主存,那么这就意味着必须把数据结构放在磁盘上,此时,因为大O模型不再适应,所以导致规则发生了变化. 不平衡二叉树的最坏情形下它具有线性的深度,由于典型的AVL树接近到最优的高度,但二叉查找树不能进到低于LogN.一棵完全二叉树的高度大约为与log2N,而一棵完全M叉树的高度大约是logmN. B树能保证少数的磁盘访问(B-树) 阶为M的B树是一棵具有下列特性的树 有关b树的一些特性,注意与后面的b+树区分: 1 关键字集合分布在整颗树中: 2 非叶节点存储直到M-1个关键字以

poj_3468 伸展树

题目大意 一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和.(这里区间指的是数列中连续的若干个数)对每次询问给出结果. 思路 1. 伸展树的一般规律 对于区间的查找更新操作,可以考虑使用伸展树.线段树等数据结构.这里使用伸展树来解决.     伸展树对数组进行维护的核心思想是,将需要维护的一组数单独提取出来,形成一棵子树(一般为整棵树的根节点的右子节点的左孩子节点 为根),然后再这个子树上进行操作.此时进行某些操作(如 ADD, SUM 等),只需要在

HYSBZ 1503 郁闷的出纳员 伸展树

题目链接: https://vjudge.net/problem/26193/origin 题目描述: 中文题面....... 解题思路: 伸展树, 需要伸展树的模板, 突然发现自己昨天看到的模板不是太好, 现在又新找了一个,  很简练, 自己将模板的实现从头到尾看了一遍, 觉得数组实现的实在是非常的巧妙, 然后自己照着敲了一遍, 边敲边看, 崩掉了.....肯定是哪里手残了, 没有必要浪费时间去改了, 有那时间不如看点别的 代码: #include <iostream> #include &

伸展树整理

伸展树 1.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置.因此,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方.伸展树应运而生.伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去. 2.操作 (1)伸展操作 伸展操作Splay(x,S)是在保持伸展树有序性的前提下,通过一系列旋转将伸展树S中的元素x调整至树的

Splay伸展树

伸展树,感觉对我这种菜鸟还是有些吃力,主要也是旋转的时候吧,把要查询的节点旋转到根节点,看网上是有两种方法,一是从上到下,一是从下到上.从上到下,是把树拆分成中树,左树和右树,始终保证目标节点在中树,不断向下把中树的节点添到右树或者左树,直到目标节点为中树的根,再将三树合并起来.另外一种从下到上,旋转操作类似AVL树中的旋转,但是判断好像不是很好写,我写的是从上到下的,另外删除也很巧妙,先把目标节点旋转到根,若此时左子树为空直接删除,否则找到左子树最右的节点当头,利用伸展树的特殊旋转就可以一步删

HNOI2002(伸展树)

营业额统计 Time Limit:5000MS     Memory Limit:165888KB     64bit IO Format:%lld & %llu Submit Status Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动