利用伸展树提高区间操作的性能
一、首先,什么是区间操作?以及各种数据结构性能对比
区间操作就是对一个序列的某个区间的所有元素进行的操作。比如,对区间所有元素增加一个值,翻转区间元素等。
对区间操作,最普通的方法就是数组。比如:对一个长为N 的序列的 [L,R]区间执行每个元素加上k 的操作,可以使用数组来保存序列,然后使用循环对[L,R]区间每个元素加k 。
代码是这样的:
//int A[],L,R,k;for i = L to RA[i] += k;
这样做的效率是 O(N),对于一个排序来说这是很好的性能,但对于一个操作来说,这并不是理想,很多二叉树的操作都能达到O( log N) 级别。
对于最典型的查找操作,普通二叉树的操作能达到O( log N) ,但是树在最坏情况下性能会退化到O(N)(比如順边的情况下) 。
平衡树能对树高度进行控制,最坏性能控制在O(log N),但是,平衡树只是控制了树的高度,而不能保证访问频率高的节点离跟越近,因此,平衡树的访问效率与节点的分布有关,如果访问频率高的节点离根很远,那么平衡树的性能就会有所降低。
因此,便有了伸展树。伸展树的特点就是:每次查找或插入节点,都会把该节点旋转到树根位置,随着操作次数增加,高频节点就会聚集在根周围,从而达到较好的性能。
二、伸展树介绍
伸展树的特点就是:每次查找或插入节点,都会把该节点旋转到树根位置,随着操作次数增加,高频节点就会聚集在根周围,从而达到较好的性能。
伸展树首先是一棵树,可以定义如下:
typedef struct Node
{int key; struct Node *lch,*rch,*parent;
}* Node ,* Tree;
伸展树的高层操作有:
高层操作 | 实现 |
---|---|
insert( t , x ) | 将x插入t中。找到x在t中的位置,插入x,然后再将x旋转到树根 |
delete( t ,x ) | 删除x。找到x,将x调到根部,将x的左子树和右子树删除后合并。 |
spilt( t , x) | 以x为界分离t。找到x,将x旋转到树根,然后将x的左子树和剩余部分分离 |
find( t , x ) | 找到x。找到x,然后将x旋转到树根。 |
join( t1 , t2 ) | 合并子树 t1和t2,要求t1所有元素小于t2的任一元素。找到t1的最大元素,并调整到根部,将t2作为根的右子树插入 |
可见,树的高层操作都依赖与旋转等基本操作:
基本操作 | 实现 |
---|---|
splay( t ,x ) | 将x调至根部。循环调用zig_zag_manager( t , x) 方法,直到x == t |
zig_zag_manager( t , x) | 旋转管理者。 找到x,分析x与父亲节点,父亲节点与祖父节点的关系,选择恰当的旋转方式。 |
下面几个函数中,设x 的父节点为 p, p的父节点为g 。 | |
zig( t , x ) | 右旋。当p是根节点,x是p的左孩子,将x右旋 |
zag( t , x ) | 左旋。当p是根节点,x是p的右孩子,将x左旋 |
zig_zig( t , x ) | 右双旋。x是p的左节点,当p是g的左节点,先将p右旋,再将x右旋 |
zag_zag( t , x ) | 左双旋。x是p的右节点,当p是g的右节点,先将p左旋,再将x左旋 |
zig_zag( t , x ) | 右旋再左旋。x是p的左节点,当p是g的右节点,先将x右旋,再将x左旋 |
zag_zig( t , x ) | 左旋再右旋。x是p的右节点,当p是g的左节点,先将x左旋,再将x右旋 |
其实上述左旋和右旋很有规律,当一个节点是左节点时,应当右旋,当一个节点是右节点时,应当左旋。
伸展树的区间操作
伸展树操作区间的思路是:
第一步,分离区间。分离长度为N的序列里的区间 [L ,R ],首先找到第L大的元素,然后以其为界进行分离操作,得到t1 = [0,L-1] 和 temp = [L ,N]。
然后,再找到 temp 中第 R-L+1 大元素,并以该元素为界进行分离操作, 得到 t2 = [L ,R] 和 t3 = [R+1, N]。这样,就成功分离出了目标区间t2 。
第二步,对目标区间进行操作。
第三步,合并区间。合并t1,t2,t3。
利用伸展树提高区间操作的性能相关推荐
- Splay伸展树入门(单点操作,区间维护)附例题模板
Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...
- BZOJ-4811: [Ynoi2017]由乃的OJ (树链剖分 线段树维护区间操作值 好题)
4811: [Ynoi2017]由乃的OJ Time Limit: 6 Sec Memory Limit: 256 MB Submit: 366 Solved: 118 [Submit][Stat ...
- poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)
好题.我做了很久,学了大牛们的区间搬移.主要的代码都有注释. #include<cstdio> #include<cstring> #include<iostream&g ...
- Tree | 伸展树
本文目录 一.伸展树的基本概念 二.Splay -- 伸展操作的原理 1.P 是根节点 2.P 不是根节点 Z字型旋转(Zig-zag) 一字型旋转(Zig-zig)-- 左 一字型旋转(Zig-zi ...
- 伸展树(Splay tree)浅谈
树看的越来越多,越来越神奇. 看伸展树这种神级数据结构之前,建议大家首先彻底明白二叉搜索树,这是万树的基础. 然后可以去看下treap,最好再去看下红黑树.如果有线段树的基础那更好了,我们会发现线段树 ...
- 伸展树的基本操作与应用 IOI2004 国家集训队论文 杨思雨
伸展树的基本操作与应用 安徽省芜湖一中 杨思雨 [关键字] 伸展树 基本操作 应用 [摘要] 本文主要介绍了伸展树的基本操作以及其在解题中的应用.全文可以分为以下四个部分. 第一部分引言,主要说明了二 ...
- Splay Tree伸展树
伸展树基本概念 伸展树的基本思想. 伸展树完全是基于局部性原理(locality)的. 局部性原理是计算机科学中非常重要的原理,很多设计,比如说多级存储器,缓存,都是基于局部性原理.简单说来就是< ...
- 数据结构--伸展树(伸展树构建二叉搜索树)-学习笔记
2019/7/16更新:封装SplayTree进入class:例题:http://poj.org/problem?id=3622 一个伸展树的板子: #include<stdio.h> # ...
- 高级数据结构实现——自顶向下伸展树
[0]README 1) 本文部分内容转自 数据结构与算法分析,旨在理解 高级数据结构实现--自顶向下伸展树 的基础知识: 2) 源代码部分思想借鉴了数据结构与算法分析,有一点干货原创代码,for o ...
最新文章
- tomcat + memcached session manager共享session
- 在iOS 中使用sleep方法 让程序暂停几秒钟
- 分布式系统理论基础 - 一致性、2PC和3PC
- arcgis api for js入门开发系列十八风向流动图
- centos打显卡驱动命令_Centos7更新内核后安装N卡驱动一键配置脚本
- 5.七个重点网络协议
- jxl java mer_导出报表出错,有没有大神懂得
- kali-扫描主机-Nmap
- mysql创建视图步骤_MySQL创建视图的详细步骤
- 在window系统上对web项目进行safair兼容测试
- 讲讲多拨的额外骚操作(多拨附加教程)
- 揭秘京东区块链开源项目——JD Chain
- Java基础之入门(一)
- 你究竟有多了解开源?InfoQ《中国开源发展研究分析 2022 》发布
- 数据分析进阶 - 使用Pyecharts搭建数据看板
- 数据结构通过链表实现班级同学通讯录
- 小米盒子 android 动画特效,小米盒子3安装这些软件 丰富娱乐功能
- linux 解压tgz文件
- php get your hands dirty,BBC地道英语:To Get your Hands Dirty 亲自动手
- cz73 读取速度慢_U盘读写速度变慢的原因详解