伸展树

伸展树(三)之 Java的实现

落花浮王杯 提交于 2020-03-12 04:45:38
概要 前面分别通过C和C++实现了伸展树,本章给出伸展树的Java版本。基本算法和原理都与前两章一样。 1. 伸展树的介绍 2. 伸展树的Java实现(完整源码) 3. 伸展树的Java测试程序 转载请注明出处: http://www.cnblogs.com/skywang12345/p/3604286.html 更多内容 : 数据结构与算法系列 目录 (01) 伸展树(一)之 图文解析 和 C语言的实现 (02) 伸展树(二)之 C++的实现 (03) 伸展树(三)之 Java的实现 伸展树的介绍 伸展树(Splay Tree)是特殊的二叉查找树。 它的特殊是指,它除了本身是棵二叉查找树之外,它还具备一个特点: 当某个节点被访问时,伸展树会通过旋转使该节点成为树根。这样做的好处是,下次要访问该节点时,能够迅速的访问到该节点。 伸展树的Java实现 1. 基本定义 public class SplayTree<T extends Comparable<T>> { private SplayTreeNode<T> mRoot; // 根结点 public class SplayTreeNode<T extends Comparable<T>> { T key; // 关键字(键值) SplayTreeNode<T> left; // 左孩子 SplayTreeNode<T>

(转)Splay伸展树模板

允我心安 提交于 2020-03-03 16:03:24
大佬博客: https://www.luogu.com.cn/blog/user19027/solution-p3369 代码: class Splay//存储规则:小左大右,重复节点记录 { #define root e[0].ch[1] //该树的根节点 private: class node { public: int v,father;//节点值,父级节点 int ch[2];//左孩子=0,右孩子=1 int sum;//自己+自己下级有多少节点。在根节点为1。 int recy;//记录自己被重复了几次 }; node e[N];//Splay树主体 int n,points;//使用存储数,元素数 void update(int x) { e[x].sum=e[e[x].ch[0]].sum+e[e[x].ch[1]].sum+e[x].recy; } int identify(int x) { return e[e[x].father].ch[0]==x?0:1; } void connect(int x,int f,int son)//连接函数。用法:connect(son,father,1/0) { e[x].father=f; e[f].ch[son]=x; }//作用:使得x的father=f,f的son=x. void rotate(int x) {

伸展树

元气小坏坏 提交于 2020-01-26 08:58:02
伸展树,或者叫自适应查找树,是一种用于保存有序集合的简单高效的数据结构。伸展树实质上是一个二叉查找树。允许查找,插入,删除,删除最小,删除最大,分割,合并等许多操作,这些操作的时间复杂度为O(logN)。由于伸展树可以适应需求序列,因此他们的性能在实际应用中更优秀。 伸展树支持所有的二叉树操作。伸展树不保证最坏情况下的时间复杂度为O(logN)。伸展树的时间复杂度边界是均摊的。尽管一个单独的操作可能很耗时,但对于一个任意的操作序列,时间复杂度可以保证为O(logN)。 2 自调整和均摊分析: 平衡查找树的一些限制: 1、平衡查找树每个节点都需要保存额外的信息。 2、难于实现,因此插入和删除操作复杂度高,且是潜在的错误点。 3、对于简单的输入,性能并没有什么提高。 平衡查找树可以考虑提高性能的地方: 1、平衡查找树在最差、平均和最坏情况下的时间复杂度在本质上是相同的。 2、对一个节点的访问,如果第二次访问的时间小于第一次访问,将是非常好的事情。 3、90-10法则。在实际情况中,90%的访问发生在10%的数据上。 4、处理好那90%的情况就很好了。 3 均摊时间边界: 在一颗二叉树中访问一个节点的时间复杂度是这个节点的深度。因此,我们可以重构树的结构,使得被经常访问的节点朝树根的方向移动。尽管这会引入额外的操作,但是经常被访问的节点被移动到了靠近根的位置,因此,对于这部分节点

伸展树的C语言实现

牧云@^-^@ 提交于 2020-01-10 22:49:11
当一个结点被访问时,它很可能不久再被访问到,伸展树就是为了达到这个目的的,其基本想法是通过一系列AVL树的旋转使被访问的结点被放到根上。如果这个结点很深,那么其路径上的许多结点也相对较深,通过重新构造可以使对这些结点的进一步访问花费的时间减少。 代码如下: 1 #include <iostream> 2 #include <stdlib.h> 3 using namespace std; 4 5 struct SplayTreeNode 6 { 7 int data; 8 struct SplayTreeNode* left; 9 struct SplayTreeNode* right; 10 }; 11 typedef struct SplayTreeNode* tree; 12 typedef struct SplayTreeNode* position; 13 14 position rotate_left(position K2); 15 position rotate_right(position K2); 16 17 //查找 18 position find(tree T, int x) 19 { 20 if (T == NULL) 21 return NULL; 22 if (x < T->data) 23 find(T->left, x); 24 else if

数据结构 树(下)

独自空忆成欢 提交于 2019-12-08 05:02:33
数据结构 树(下) 一、概述    AVL树、伸展树、红黑树搜索树算法保证最坏情况或者一系列操作情况下,搜索、插入和删除的操作的时间复杂度是 O(logn) 。本文 主要内容包含:平衡搜索树中的AVL树、伸展树、(2,4)树、红黑树 和(a,b)树、B树等实际运用的树数据结构。 二叉搜索树的删除 二、AVL树 1、基本知识 1、AVL树是维持对数 O(logn) 的高度的特殊二叉搜索树。“高度”指根节点到叶子节点最长路径上的节点的数量。“None”的孩子的高度是0,叶子节点的高度是1,父节点是叶子节点的高度加1 2、AVL树具有 高度平衡属性:对于树T的每个位置P,P的孩子的高度最多相差 1。AVL树子树也是一颗AVL树! 3、一个高度为h(h≥3)的拥有最少节点的AVL树,必须有两颗子树:一颗高度 h-1,另一颗高度为 h-2:n(h)=1+n(h-1)+n(h-2) h≥3 (n(1)=1、n(2)=2) 4、AVL树的高度h和节点总数n的关系: h < 2log n +2 5、AVL树平衡因子是指位置p的两颗子树高度差 (左树减右树/右树减左树) ,平衡因子 的绝对值 不大于1。 2、更新操作 1、插入,AVL树在叶子节点产生一个新的节点插入新节点p,导致p的祖先节点不满足高度平衡属性,通过trinode重组,两次“旋转”重建树T,使其满足AVL树的高度平衡属性 2、删除

HDU 4453 Looploop(伸展树应用,数列环)

匿名 (未验证) 提交于 2019-12-03 00:18:01
题意: 给定一个环,和一个原点,对这个环有以下操作 : add x 操作 : 从队首开始的的连续 k2 个数都加上 x ֵ . reverse 操作 : 从队首开始的连续 k1 个数都翻转 insert x 操作 : 在第一个元素与第二个元素之间插入一个 x ֵ delete 操作 : 删除原点,新原点顺时针移动一下 move 1 操作 : 原点逆时针移动一个 move 2 操作 : 原点顺时针移动一个 query 操作 : 返回原点元素的值 题解: 伸展树的应用: 正常的伸展树是对数列进行操作,而本题可看作是对一个首尾相连的数列进行操作; 标记源点的位置 ,每次 add 和 reverse 的时候,只需将源点反转至根节点,把根节点左边的删除,再插入到剩余序列的尾部,然后再进行更新即可。 #include<bits/stdc++.h> using namespace std; const int maxn = 2e5+99; #define keyv ch[ch[root][1]][0] int pre[maxn],sz[maxn],rev[maxn],add[maxn],ch[maxn][2]; int root,tot1,key[maxn]; int tot2,s[maxn]; int tp; int n,q,k1,k2; int a[maxn]; void newnode

浅谈伸展树(Splay)

做~自己de王妃 提交于 2019-11-26 20:33:47
//本文是一个暂时的小记,有不对的请大佬们指出~ 真正大佬的在这http://blog.csdn.net/clove_unique/article/details/50630280 伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由丹尼尔·斯立特Daniel Sleator和罗伯特·恩卓·塔扬Robert Endre Tarjan在1985年发明的。 在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。 它的优势在于不需要记录用于平衡树的冗余信息。 (本段来自百度) Splay的基本操作 get操作 主要用来查找x结点属于其父亲结点的左儿子还是右儿子 int get(int x) { return son[fa[x]][1]==x; } update操作 主要是更新size值 (有的时候也会更新其他) void update(int x) { if (x) { size[x]=1; if

树-伸展树(Splay Tree)

帅比萌擦擦* 提交于 2019-11-26 14:58:14
伸展树概念 伸展树(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) 除了拥有二叉查找树的性质之外,伸展树还具有的一个特点是:当某个节点被访问时,伸展树会通过旋转使该节点成为树根。这样做的好处是,下次要访问该节点时,能够迅速的访问到该节点。 假设想要对一个二叉查找树执行一系列的查找操作。为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生,它是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。 相比于"二叉查找树"和"AVL树",学习伸展树时需要重点关注是"伸展树的旋转算法"。 伸展树实现 伸展树的节点包括的几个组成元素: (01) key -- 是关键字,是用来对伸展树的节点进行排序的。 (02)