平衡二叉树之伸展树

伸展树(Splay Tree),或者叫自适应查找树,插入、查找和删除操作的时间都为O(logn)。

伸展树的目的是使被查频率高的那些条目就应当经常处于靠近树根的位置。它的做法是在每次查找后,将被查找的节点splay到根节点。

使用伸展树需要符合90-10法则:在实际情况中,90%的访问发生在10%的数据上。

优点:不需要记录用于平衡树的冗余信息

伸展树节点结构:

struct SplayTree
{
 int value;
 int lchild; //左儿子在数组中的下标
 int rchild; //右儿子在数组中的下标
 int parent;  //为0表示是根节点
};

SplayTree s[MAX];

有两个基本的操作:

1、伸展操作Splay(T,i)是在保持伸展树有序性的前提下,通过一系列旋转将伸展树T中的元素i调整至树的根部

void Zig(int i){ //节点i右旋转
 int j = s[i].parent;
 s[j].lchild = s[i].rchild; //i的右儿子成为j的左儿子
 s[s[i].rchild].parent = j;
 s[i].rchild = j;
 s[i].parent = s[j].parent;
 s[j].parent = i;
 if(s[i].parent != 0){
  if(s[s[i].parent].lchild == j){
   s[s[i].parent].lchild = i;
  }else{
   s[s[i].parent].rchild = i;
  }
 }
}
void Zag(int i){//节点i左旋转
 int j = s[i].parent;
 s[j].rchild = s[i].lchild;
 s[s[i].lchild].parent = j;
 s[i].lchild = j;
 s[i].parent = s[j].parent;
 s[j].parent = i;
 if(s[i].parent != 0)
 {
  if(s[s[i].parent].lchild == j)
  {
   s[s[i].parent].lchild = i;
  }
  else
  {
   s[s[i].parent].rchild = i;
  }
 }
}
void Splay(int T, int i){
 while(s[i].parent != T){
  if(s[s[i].parent].parent == T){ //父节点是根节点
   if(s[s[i].parent].lchild == i) Zig(i); //如果是父节点的左儿子,则右旋
   else Zag(i); //如果是父节点的右儿子,则左旋
   break;
  }else{
   int j = s[i].parent;
   int k = s[j].parent;
   if(s[k].lchild == j && s[j].lchild == i){
    Zig(j);
    Zig(i);
   }else if(s[k].rchild == j && s[j].rchild == i){
    Zag(j);
    Zag(i);
   }else if(s[k].lchild == j && s[j].rchild == i){
    Zag(i);
    Zig(i);
   }else if(s[k].rchild == j && s[j].lchild == i){
    Zig(i);
    Zag(i);
   }
  }
 }
}

2、Join(T1,T2):将两个伸展树T1与T2合并成为一个伸展树。其中T1的所有元素都小于T2的所有元素。首先,我们找到伸展树T1中最大的一 个元素i,再通过Splay(T1,i)将i调整到伸展树T1的根。然后再将T2作为i节点的右子树。这样,就得到了新的伸展树i。

int Join(int T1, int T2){
 int i = T1;
 while(s[i].rchild != -1){
  i = s[i].rchild;
 }
 Splay(0, i);
 s[i].rchild = T2;
 s[T2].parent = i;
 return i;
}

其他操作大体与二叉查找树中的操作一样,只需在操作后调用Splay进行元素调整

时间: 2024-11-04 16:40:01

平衡二叉树之伸展树的相关文章

伸展树

伸展树(Splay Tree)树平衡二叉查找树的一种,具有二叉查找树的所有性质.在性能上又比普通的二叉查找树有所改进:普通的二叉查找树在最坏情况下的查找操作的时间复杂度为O(n)(当二叉树退化成一条链的时候),而伸展树在任何情况下的平摊时间复杂度均为 O(log2n). 特性 和普通的二叉查找树相比,具有任何情况下.任何操作的平摊O(log2n)的复杂度,时间性能上更好 和一般的平衡二叉树比如 红黑树.AVL树相比,维护更少的节点额外信息,空间性能更优,同时编程复杂度更低 在很多情况下,对于查找

查找——清晰图解伸展树SplayTree

伸展树 伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它由Daniel Sleator和Robert Tarjan创造,后者对其进行了改进. 假设想要对一个二叉查找树执行一系列的查找操作.为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置.于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方.splaytree应运而生.splaytree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转

wikioi 1396 伸展树(模板)

题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题.经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 = min{|该天

数据结构之伸展树

1. 概述 二叉查找树(Binary Search Tree,也叫二叉排序树,即Binary Sort Tree)能够支持多种动态集合操作,它可以用来表示有序集合.建立索引等,因而在实际应用中,二叉排序树是一种非常重要的数据结构. 从算法复杂度角度考虑,我们知道,作用于二叉查找树上的基本操作(如查找,插入等)的时间复杂度与树的高度成正比.对一个含n个节点的完全二叉树,这些操作的最坏情况运行时间为O(log n).但如果因为频繁的删除和插入操作,导致树退化成一个n个节点的线性链(此时即为一个单链表

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拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动