学习Splay的时候参考了很多不同的资料,然而参考资料太杂的后果就是模板调出来一直都有问题,尤其是最后发现网上找的各种资料均有不同程度的错误。

好在啃了几天之后终于算是啃下来了。

Splay也算是平衡树的一种,但是跟AVL树、SBT不同的是,Splay并不是一直保持严格的平衡,因此在速度上可能要慢一些,但是统计学上仍能保证Splay具有O(logn)的均摊复杂度。

Splay原生不需要附加任何空间,它的先天优势是其特有的Splay操作可以非常灵活地改变整棵树的结构形态,完成一般线段树、平衡树做不到的任务。

  • 基本操作-左右旋

Splay的基本操作与其他平衡树相似,都是进行结点的左右旋转。与之前写的SBT相比,Splay除了左右儿子域以外还需要一个father域,这个是因为下面的Splay操作需要用到父节点来判断当前的形态。

  • 核心操作-splay

Splay(x,y)的作用是将当前点x旋转到y的子结点上,一般写y=0时则将x旋转到整棵树的根。这个操作在splay的所有函数中基本上最后都要加上,简单的理解就是将常用的结点尽可能地上移到深度较浅的地方,据统计若去掉函数最后对操作结点的splay,则整个程序将会慢上数倍。

splay基本的想法是根据当前结点父节点形态的不同,分成四种情况,逐步将结点旋转到根上。

  • 进阶操作

插入、查找值、查找第k个等等...基本与普通的二叉查找树相似,但是记得在最后要加上splay,将使用过的结点旋转到根。

特殊的删除操作:

splay本身是一棵二叉搜索树,可以进行一般的删除操作。另外,二叉搜索树的性质配合splay的操作可以做到O(logn)动态删除一整个区间的结点,而一般的平衡树则只能一个一个删除。

例如:删除大于l且小于r的数,先将序号小于l的最大结点伸展到根,序号大于r的最小的结点伸展到根的右子树,则此时,r的后继结点的左子树中就存放着从l到r的所有结点,此时只要把这棵子树整个断开即可。

............

/* ***********************************************
MYID    : Chen Fan
LANG    : G++
PROG    : Splay Tree
************************************************ */#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;#define MAXN 100000int sons[MAXN][2];
int father[MAXN],size[MAXN],data[MAXN];
int spt=0,spttail=0;void rotate(int x,int w) //rotate(node,0/1)
{int y=father[x];sons[y][1-w]=sons[x][w];if (sons[x][w]) father[sons[x][w]]=y;father[x]=father[y];if (father[y])if (y==sons[father[y]][0]) sons[father[y]][0]=x;else sons[father[y]][1]=x;sons[x][w]=y;father[y]=x;size[x]=size[y];size[y]=size[sons[y][0]]+size[sons[y][1]]+1;
}void splay(int x,int y) //splay(node,position)
{if (!x) return ;while(father[x]!=y){if (father[father[x]]==y)if (x==sons[father[x]][0]) rotate(x,1);else rotate(x,0);else if (father[x]==sons[father[father[x]]][0])if (x==sons[father[x]][0]){rotate(father[x],1);rotate(x,1);} else {rotate(x,0);rotate(x,1);}else if (x==sons[father[x]][1]){rotate(father[x],0);rotate(x,0);} else {rotate(x,1);rotate(x,0);}}if (!y) spt=x;
}void search(int x,int w)
{while(data[x]!=w){if (w<data[x]){if (sons[x][0]) x=sons[x][0];else break;} else if (w>data[x]){if (sons[x][1]) x=sons[x][1];else break;}}splay(x,0);
}void insert(int w) //insert(value)
{spttail++;data[spttail]=w;size[spttail]=1;sons[spttail][0]=0;sons[spttail][1]=0;if (!spt){father[spttail]=0;spt=spttail;} else {int x=spt;while(1){size[x]++;if (w<data[x])if (sons[x][0]) x=sons[x][0];else break;else if (sons[x][1]) x=sons[x][1];else break;}father[spttail]=x;if (w<data[x]) sons[x][0]=spttail;else sons[x][1]=spttail;splay(spttail,0);}
}void select(int x,int v) //select(root,k)
{while(v!=size[sons[x][0]]+1){if (v<=size[sons[x][0]]) x=sons[x][0];else {v-=size[sons[x][0]]+1;x=sons[x][1];}}splay(x,0);
}int succ(int t)
{t=sons[t][1];while(sons[t][0]) t=sons[t][0];splay(t,0);return t;
}void del(int x) //del(number)
{splay(x,0);int y=sons[x][0];while(!sons[y][1]){y=sons[y][1];}int z=sons[x][1];while(!sons[z][0]){z=sons[z][0];}if (y+z==0){spt=0;spttail=0;return ;}if (y){splay(y,0);size[y]--;}if (z){splay(z,y);sons[z][0]=0;size[z]--;}
}int rank(int v) //rank(value)
{search(spt,v);return size[sons[spt][0]]+1;
}int main()
{memset(father,0,sizeof(father));memset(size,0,sizeof(size));memset(sons,0,sizeof(sons));memset(data,0,sizeof(data));spt=0;spttail=0;return 0;
}

转载于:https://www.cnblogs.com/jcf94/p/4333497.html

伸展树 Splay 模板相关推荐

  1. 伸展树(Splay tree)图解与实现

    伸展树(Splay tree)图解与实现 伸展树(Splay tree)图解与实现_小张的专栏-CSDN博客_splay树 Splay树详解 Splay树详解 - 秦淮岸灯火阑珊 - 博客园 平衡树 ...

  2. splay tree java_伸展树(splay tree)自顶向下的算法

    伸展树(splay tree)是一种能自我调整的二叉搜索树(BST).虽然某一次的访问操作所花费的时间比较长,但是平摊(amortized) 之后的访问操作(例如旋转)时间能达到O(logn)的复杂度 ...

  3. [学习笔记] 伸展树splay详解+全套模板+例题[Luogu P3369 【模板】普通平衡树]

    文章目录 引入概念 全套模板 变量声明 update ==rotate旋转== splay操作 insert插入 delete删除 查找x的位置 查找第k大 前驱/后继 极小值-inf和极大值inf的 ...

  4. 伸展树(Splay tree)浅谈

    树看的越来越多,越来越神奇. 看伸展树这种神级数据结构之前,建议大家首先彻底明白二叉搜索树,这是万树的基础. 然后可以去看下treap,最好再去看下红黑树.如果有线段树的基础那更好了,我们会发现线段树 ...

  5. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  6. sgu 187 Twist and whirl - want to cheat 伸展树(splay)

    裸的区间翻转..直接写个splay就行... #include <iostream> #include <cstdio> #include <algorithm> ...

  7. AVL树、splay树(伸展树)和红黑树比较

    AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...

  8. HYSBZ 1503 郁闷的出纳员 伸展树

    题目链接: https://vjudge.net/problem/26193/origin 题目描述: 中文题面....... 解题思路: 伸展树, 需要伸展树的模板, 突然发现自己昨天看到的模板不是 ...

  9. 伸展树(二) - C++实现

    概要 上一章介绍了伸展树的基本概念,并通过C语言实现了伸展树.本章是伸展树的C++实现,后续再给出Java版本.还是那句老话,它们的原理都一样,择其一了解即可. 目录 1. 伸展树的介绍 2. 伸展树 ...

最新文章

  1. pl sql如何调试oracle存储过程,PL/SQL Developer中调试oracle的存储过程
  2. java maven junit_【JUnit】JUnit 与 maven 集成
  3. python startswitch_使用python esl 实现FreeSWITCH自动外呼
  4. 好记性不如烂笔头——.NET运行原理
  5. 图片生成html_markdown 生成头条文章的一个实现
  6. php底层运行机制(二)
  7. verilog中generate用法及参数传递(转)
  8. 小数保留4位_实验结果保留几位有效数字?
  9. Java WebService视频教程
  10. 数字图像处理(极简) 第一章 概述(docx)
  11. vue高拍仪拍照后上传服务器回显到Upload(记录)
  12. oppo9s刷机教程_OPPOR9s线刷救砖教程及刷机包下载
  13. linux看温度命令,linux查看cpu温度命令
  14. python-求m+mm+mmm+mmmm+ ...
  15. python查文章字数
  16. strtolower() 函数
  17. 使用IMU与轮速计进行单线激光雷达的运动畸变校正
  18. H5接入微信公众号方法(超详细)
  19. 中国移动诺基亚联手推出智能机
  20. 直播带货没销量,深度挖掘李佳琪带货思维模式,你也能成功!

热门文章

  1. matlab验证对称三相电路,不对称三相电路中,中线的电流为()。 A.0 B. C. D....
  2. python写的一个贴吧爬虫_Python-简单百度贴吧爬虫
  3. stcisp一直检测单片机_三种方法对比:STC51单片机实现免冷启动
  4. 多重继承与虚继承编程实验
  5. c语言现代方法16章 基础、课后习题、基础等
  6. 【C++11新特性】 - 空间配置allocator类
  7. 请举出OSI七层模型在实际应用中的实例
  8. 二阶偏微分方程组 龙格库塔法_深度科普---电磁波(三):无激励下的真空中的Maxwell方程组的解...
  9. SWIFT(Society for Worldwide Interbank Financial SWIFT Telecommunications---环球同业银行金融电讯协会)
  10. ant基本标签 及import properties