Splay,伸展树。之所以先写这个课内并不怎么常用的数据结构,是因为本人非常喜欢Splay,我觉得这是非常有美感且灵活的一种平衡树。在此先声明,我的伸展树写法来源于CLJ大牛,基础好的同学可以去他的博客中看看他的Splay实现模板,我的实现仅仅借鉴了CLJ大神的一点实现技巧而已。我的博文《心中的大牛博客列表》中有CLJ大神的博客链接。

还有很多同学可能并不了解Splay的思想,那么可以去看sqybi的文章《The magical splay》,百度文库就可以搜索到。这篇文章是我看过的里讲解splay最清晰的。里面的图和讲解都非常棒,里面的代码是Pascal的,但是没关系,只会C++的同学可以看我的代码。

在此先要讲解一下CLJ大神的这个splay实现技巧:充分利用C/C++中将bool型的true和false的值设置为1和0的特点,将树的每个节点的左右孩子指针用如下方式定义——node *son[2]。如此一来,son[0]便是左孩子,son[1]便是右孩子。此时,便可以在实现中,将左侧、右侧操作的代码写成一段,利用一个bool型变量来区分就好了。因此,代码基本会少一半!

我这么说大家肯定糊里糊涂的,不废话了,直接上代码,大家仔细看看代码就懂了。

题目:sjtuoj 1221。

清爽版:暂无。因为Splay的实现代码还是比较长的,因此并不考虑直接写,代码反而会很乱。

类实现版:

 /*
* 题目:sjtuoj 1221
* oj链接:http://acm.sjtu.edu.cn/OnlineJudge
*/
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
using namespace std; const int minInt=<<;
const int maxInt=minInt-; struct dot
{
int c,num,size;
dot *son[],*up; // son[false]是左孩子,son[true]是右孩子,up是父亲 dot(int value=) { c=value; num=size=; son[false]=son[true]=up=; }
bool get(dot *lr) { return son[true]==lr; }
void add_up(int n) { for(dot *u=this;u;u=u->up) u->size+=n; }
dot* born(bool k,dot* lr)
{
son[k]=lr;
if(lr) { lr->up=this; add_up(lr->size); }
return this;
}
dot* kill(bool k)
{
dot *lr=son[k]; son[k]=;
if(lr) { lr->up=; add_up(-lr->size); }
return lr;
}
}; int vv(dot *u) { return u?u->c:; }
int nn(dot *u) { return u?u->num:; }
int ss(dot *u) { return u?u->size:; } class Splay
{
public:
dot *Root,*Min,*Max;
private:
void zg(dot *x)
{
dot *y=x->up,*z=y->up;
bool i=(z?z->get(y):),k=y->get(x); // 此处i==0时,i无意义 if(z) z->kill(i);
x->born(!k,y->born(k,y->kill(k)->kill(!k)));
if(z) z->born(i,x); if(y==Root) Root=x; // 维护Root,可能也是保险?no!This is useful!
}
void splay(dot *x,dot *up=) // 将x旋转到其父亲为up的位置
{
dot *y,*z;
while(x->up!=up) // x还没到指定位置
{
y=x->up; if(y->up==up) { zg(x); break; } // 如果y是指定位置,则将x旋转到y
z=y->up; zg((z->get(y)==y->get(x))?y:x); zg(x); // 将x旋转到z即可
}
}
void recycle(dot *p)
{
if(!p) return;
recycle(p->son[false]); recycle(p->son[true]);
delete p;
}
dot* next(dot *p,bool k)
{
splay(p); dot *u=p->son[k];
while(u->son[!k]) u=u->son[!k];
return u;
}
public:
Splay()
{
Min=Root=new dot(minInt); Max=new dot(maxInt);
Min->born(true,Max);
}
int size() { return Root->size-; }
dot* Find(int c)
{
dot *u=Root;
while(u&&u->c!=c) u=u->son[c>u->c];
return u;
} void Insert(int c)
{
bool k;
dot *u=,*v=Root; while(v&&v->c!=c)
{
u=v;
k=(c>v->c);
v=v->son[k];
}
if(v) { ++v->num; v->add_up(); } else splay(u->born(k,new dot(c))->son[k]);
}
void Delete(int c)
{
dot *p=Find(c),*l,*r; --p->num; p->add_up(-);
if(p->num==)
{
l=next(p,false); r=next(p,true);
splay(l); splay(r,Root);
recycle(r->kill(false));
}
}
void Delete(int cl,int cr)
{
dot *L,*R,*l,*r; Insert(cl); Insert(cr);
L=Find(cl); R=Find(cr); l=next(L,false); r=next(R,true);
splay(l); splay(r,Root);
recycle(r->kill(false));
}
int Find_ith(int i,dot *u) // 这里的三种情况,用到了其先后顺序,故顺序不能轻易改变
{
int size=ss(u->son[false]),mid=u->num;
if(i<=size) return Find_ith(i,u->son[false]);
if(i<=size+mid) return u->c;
return Find_ith(i-size-mid,u->son[true]);
}
}; Splay A; // 创建一棵Splay树,名叫A int main()
{
// 本题,假设题目数据均在 minInt+1 ~ maxInt-1 范围内
int n,x,y; cin>>n;
string order;
for(int i=;i<=n;++i)
{
cin>>order;
if(order=="insert") { cin>>x; A.Insert(x); }
if(order=="delete") { cin>>x; A.Delete(x); }
if(order=="delete_less_than") { cin>>y; A.Delete(minInt+,y-); }
if(order=="delete_greater_than") { cin>>x; A.Delete(x+,maxInt-); }
if(order=="delete_interval") { cin>>x>>y; A.Delete(x+,y-); }
if(order=="find") { cin>>x; cout<<(A.Find(x)?"Y":"N")<<endl; }
if(order=="find_ith")
{
cin>>x;
if(A.size()<x) { cout<<"N"<<endl; continue; }
cout<<A.Find_ith(x+,A.Root)<<endl; // 有一个Min,所以得找第x+1个
}
} return ;
}

《数据结构》C++代码 Splay的更多相关文章

  1. 【数据结构】平衡树splay和fhq—treap

    1.BST二叉搜索树 顾名思义,它是一棵二叉树. 它满足一个性质:每一个节点的权值大于它的左儿子,小于它的右儿子. 当然不只上面那两种树的结构. 那么根据性质,可以得到该节点左子树里的所有值都比它小, ...

  2. [数据结构]伸展树(Splay)

    #0.0 写在前面 Splay(伸展树)是较为重要的一种平衡树,理解起来也依旧很容易,但是细节是真的多QnQ,学一次忘一次,还是得用博客加深一下理解( #1.0 Splay! #1.1 基本构架 Sp ...

  3. codeforces733D. Kostya the Sculptor 偏序cmp排序,数据结构hash,代码简化

    对于n==100.1,1,2或者1,2,2大量重复的形状相同的数据,cmp函数最后一项如果表达式带等于,整个程序就会崩溃 还没有仔细分析std::sort的调用过程,所以这里不是很懂..,mark以后 ...

  4. 【算法与数据结构专场】BitMap算法基本操作代码实现

    上篇我们讲了BitMap是如何对数据进行存储的,没看过的可以看一下[算法与数据结构专场]BitMap算法介绍 这篇我们来讲一下BitMap这个数据结构的代码实现. 回顾下数据的存储原理 一个二进制位对 ...

  5. 《数据结构》C++代码 前言

    现在大二正在上<数据结构>课,课内的书上代码实现很喜欢无脑用类.变量名字很长,而且常常实现太繁琐,并且代码有些无法运行,这些对于老手无所谓,但初学者看起来却会很不舒服.因此写点自己实现这些 ...

  6. C++基础代码--20余种数据结构和算法的实现

    C++基础代码--20余种数据结构和算法的实现 过年了,闲来无事,翻阅起以前写的代码,无意间找到了大学时写的一套C++工具集,主要是关于数据结构和算法.以及语言层面的工具类.过去好几年了,现在几乎已经 ...

  7. python算法与数据结构-二叉树的代码实现(46)

    一.二叉树回忆 上一篇我们对数据结构中常用的树做了介绍,本篇博客主要以二叉树为例,讲解一下树的数据结构和代码实现.回顾二叉树:二叉树是每个节点最多有两个子树的树结构.通常子树被称作“左子树”(left ...

  8. bzoj1588: [HNOI2002]营业额统计 splay瞎写

    最近各种瞎写数论题,感觉需要回顾一下数据结构 写一发splay冷静一下(手速过慢,以后要多练练) 用splay是最直接的方法,但我感觉离散一波应该可以做出来(没仔细想过) 现在没有很追求代码优美,感觉 ...

  9. 文艺平衡树 Splay 学习笔记(1)

    (这里是Splay基础操作,reserve什么的会在下一篇里面讲) 好久之前就说要学Splay了,结果苟到现在才学习. 可能是最近良心发现自己实在太弱了,听数学又听不懂只好多学点不要脑子的数据结构. ...

随机推荐

  1. 显示、更改ubuntu linux主机名(计算机名)

    在bash中输入hostname可以显示计算机名.Linux和windows都可以使用这条指令. 主机名保存在/etc/hostname文件中 需要进入Root权限才可以修改该文件. sudo ged ...

  2. MSD_radix_sort

    一.这次是在上一次尝试基础上进行的,预期是达到上次性能的9倍. MSD的基本手法就是不断切片.每一步都是把整体数据切割成256片,如上图所示,实际情况切片未必均匀,有的slice内可能一个元素也没有. ...

  3. POJ-2155 Matrix---二维树状数组+区域更新单点查询

    题目链接: https://vjudge.net/problem/POJ-2155 题目大意: 给一个n*n的01矩阵,然后有两种操作(m次)C x1 y1 x2 y2是把这个小矩形内所有数字异或一遍 ...

  4. 类似LCS,构成目标单词(POJ2192)

    题目链接:http://poj.org/problem?id=2192 解题报告: 1.类似最长公共子序列,dp[i][j]表示用s1前i个字符和s2前j个字符来构成目标单词的一部分,是否成功 2.状 ...

  5. 一步步做程序优化-讲一个用于OpenACC优化的程序(转载)

    一步步做程序优化[1]讲一个用于OpenACC优化的程序 分析下A,B,C为三个矩阵,A为m*n维,B为n*k维,C为m*k维,用A和B来计算C,计算方法是:C = alpha*A*B + beta* ...

  6. 第39章 ETH—Lwip以太网通信—零死角玩转STM32-F429系列

    第39章     ETH—Lwip以太网通信 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  7. 洛谷P1762 偶数(找规律)

    题目描述 给定一个正整数n,请输出杨辉三角形前n行的偶数个数对1000003取模后的结果. 输入输出格式 输入格式: 一个数 输出格式: 结果 输入输出样例 输入样例#1: 复制 6 输出样例#1:  ...

  8. Java OOP——第七章 多线程

    1.进程:是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间): Eg:用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间.当用户再次点击左面的IE浏览器, ...

  9. 解决.NET Core R1中文乱码问题

    今天写了一个简单的.NET Core RC1控制台程序,发现中文显示一直是乱码.查看操作系统设置,没有问题:查看源文件编码,也没有问题:甚至查看了Console字符编码相关的注册表,依然没有发现问题. ...

  10. python中的字符串内置方法小结

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- ''' name="my wife is mahongyan" ---------- ...