「学习笔记」平衡树——splay 一

这篇具有很好参考价值的文章主要介绍了「学习笔记」平衡树——splay 一。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Splay,一种平衡树,同时也是二叉排序树,与 Treap 不同,它不需要维护堆的性质,它由 Daniel Sleator 和 Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二叉树,它会将一个节点沿着到根的路径旋转上去。
空间效率:\(O_n\)
摊平时间效率:\(O_{logn}\)
建议先学会 Treap。

存储结构

int ch[N][2],fa[N];//左孩子,右孩子,父亲 
ll val[N],siz[N],cnt[N];//点值 

数组存储,也可以用结构体。

基本操作

一、旋转

与 treap 的旋转无太大差异,只要注意更新父节点就行了,记得要更新 \(siz\)
Splay 的旋转函数的参数,是转上去的那个数值,这里与 Treap 不同,Treap 是转下来的数值。
这里旋转一定要注意次序,明白先处理哪个,再处理哪个,否则会 RE!
一定要先处理 \(x\)\(y\) 的孩子,再处理 \(x\)\(y\)

void pushup(int id)//更新siz 
{
    siz[id]=siz[ch[id][0]]+siz[ch[id][1]]+cnt[id];
}
void spin(int x)
{
    rint y=fa[x],z=fa[y],d=(ch[y][1]==x);//d 判断x是y的左孩子还是右孩子 
    ch[z][ch[z][1]==y]=x,fa[x]=z;//处理x与z的关系 
    ch[y][d]=ch[x][d^1],fa[ch[x][d^1]]=y;//处理y的孩子与x的孩子的关系 
    ch[x][d^1]=y;fa[y]=x;//处理y与x的关系 
    pushup(y);//先更新y 
    pushup(x);//在更新x 
}

二、伸展

情况一

\(x\) 要移动到父节点的位置。
「学习笔记」平衡树——splay 一
自己懒得画了,图扒的教练的
直接旋转 \(x\) 即可。

情况二

\(x\) 点要移到到 \(g\) 或更向上的位置且 \(g\) -> \(p\)\(p\) -> \(x\) 是同一方向。
「学习笔记」平衡树——splay 一
这里要先旋转 \(p\),再旋转 \(x\)

情况三

\(x\) 点要移到到 \(g\) 或更向上的位置且 \(g\) -> \(p\)\(p\) -> \(x\) 不是是同一方向。
「学习笔记」平衡树——splay 一
这里旋转两次 \(x\)
其实,到这里你会发现,最后一次都是旋转 \(x\)

void splay(int x,int goal)
{
    while(fa[x]!=goal)//判断是否已经到目标点的下边 
    {
        rint y=fa[x],z=fa[y];
        if(z!=goal)//判断是情况一还是情况二、三 
            (ch[y][0]==x)^(ch[z][0]==y)?spin(x):spin(y);
        //判断是情况二还是情况三 
        spin(x);
    }
    if(goal==0)    root=x;//如果移动到了根节点,则更新根节点 
}

三、插入节点

只要记得处理父节点就行了。

void insert(ll x)
{
    int u=root,fat=0;
    while(u&&val[u]!=x)//先向下找 
    {
        fat=u;
        u=ch[u][x>val[u]];
    }
    if(u)    cnt[u]++;
    else
    {
        u=++tot;
        if(fat)    ch[fat][x>val[fat]]=u;//如果不是根节点,更新孩子节点 
        fa[u]=fat;//插入操作 
        val[u]=x;
        siz[u]=1;
        cnt[u]=1;
    }
    splay(u,0);//每次都要伸展,避免成链 
}

四、查找结点

按照二叉排序树找到节点,然后将该节点伸展到到根节点就行了。

void find(ll x)
{
    int u=root;
    if(!u)    return;//不存在该节点,直接返回 
    while(ch[u][x>val[u]]&&x!=val[u])//找到该节点的位置 
        u=ch[u][x>val[u]];
    splay(u,0);//伸展 
}

五、查找前驱后继

先将要查找的值的位置或相邻的位置伸展到根节点,然后在左右子树中搜索。

int get(ll x,int d)//d:0找前驱 1找后继 
{
    find(x);//先伸展 
    int u=root;
    if((val[u]>x&&d)||(val[u]<x&&!d))    return u;
    //如果该节点已经符合要求,直接返回位置 
    u=ch[u][d];//找到左右子树 
    while(ch[u][d^1])    u=ch[u][d^1];
    //找左子树中最大的或右子树中最小的(关键看你找前驱还是后继) 
    return u;//返回前驱或后继的位置 
}

六、删除节点

先找到前驱和后继,将前驱伸展到根节点,将后继伸展到前驱下面,根据二叉查找树的性质,后继的左孩子就是我们要删的点,进行操作即可。

void del(ll x)
{
    int pre=get(x,0),nxt=get(x,1);//找前驱后继 
    splay(pre,0),splay(nxt,pre);//伸展 
    int id=ch[nxt][0];//要删除的点 
    if(cnt[id]>1)//如果这个数值有重复,直接--cnt即可 
    {
        --cnt[id];
        splay(id,0);//伸展 
    }
    else
    {
        ch[nxt][0]=0,fa[id]=0;//先切断联系 
        val[id]=0,cnt[id]=0,siz[id]=0;//再进行删除 
        pushup(nxt),pushup(pre);//最后更新siz 
    }
}

其他文章

平衡树——splay 二
平衡树——splay 三文章来源地址https://www.toymoban.com/news/detail-471974.html

到了这里,关于「学习笔记」平衡树——splay 一的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法学习笔记(21): 平衡树(二)

    平衡树(一)链接:算法学习笔记(18): 平衡树(一) - jeefy - 博客园 本文中将讲述一下内容: 可持久化Treap 基于 Trie 的 类 平衡树(后文称之为 BSTrie ) BSTrie的可持久化 可持久化Treap基于FHQ-Treap。其实不难发现,FHQ-Treap在分裂和合并时在每一层只对一个结点产生影响。于是我

    2024年02月04日
    浏览(30)
  • 【学习笔记】fhq Treap实现文艺平衡树

    没有学习过 fhq Treap 的可以看我上一篇文章,看过的建议去再看看分裂和合并操作 在上一篇文章中提到,fhq Treap 可以支持比较多的操作,文艺平衡树就是其中一种,其实就是可以实现 区间操作 (翻转)的平衡树 板子在这里 fhq Treap 实现文艺平衡树的步骤是: 将树按大小分裂

    2024年02月10日
    浏览(30)
  • 论文笔记:基于概念漂移的在线类非平衡学习系统研究

    论文:A Systematic Study of Online Class Imbalance Learning With Concept Drift 发表:2018年发表在TNNLS上 源代码:? 作为一个新兴的研究课题,在线类非平衡学习往往结合了类非平衡和概念漂移的挑战。它处理具有非常倾斜的类分布的数据流,其中可能发生概念漂移。它最近受到越来越多的

    2024年02月11日
    浏览(63)
  • 一种解决STM32多串口同时收发的方法

    在做项目中,遇到了同时调用串口通信时程序崩溃的问题,在项目中,串口1用作调试串口,串口2用作MQTT通信串口,串口3用作下位机通信串口, 串口1重定向以后,用库函数自带的printf函数打印字符串 串口2使用自己写的u2_printf函数,即va_list这套变参宏定义后使用vsprintf函数

    2023年04月21日
    浏览(26)
  • 自己开发一种编程语言,可以同时开发鸿蒙,Android ios的三个平台的应用

    要开发一种可以在鸿蒙操作系统、Android操作系统和iOS操作系统上运行的编程语言,需要考虑以下几个方面: 语言设计:首先需要设计一种语言,该语言应具备跨平台的特性,能够在不同操作系统上编写应用程序。这需要考虑语法、语义、类型系统等方面的设计。 编译器或解

    2024年02月04日
    浏览(36)
  • 【论文笔记】IntelliLight智能交通灯:一种基于强化学习的智能交通信号灯控制方法

    博客声明:本文仅为个人论文阅读笔记,大部分原文对照的中文为翻译而来,只对其中错误明显的部分作了修改。其他一些个人理解不到位或有误的地方也尽请见谅。 标题原文: IntelliLight:A Reinforcement Learning Approach for Intelligent Traffic Light Control 论文来源: Proceedings of the 24

    2024年04月12日
    浏览(36)
  • 物联网|ARM|Keil同时安装Keil的C51、C251和MDK|增加V5编译器|物联网开发系列课程之零基础玩转Cortex-M系列CPU-学习笔记(1)

    1.物联网的定义 利用局部网络或互联网等通信技术把传感器、控制器、机器、人员和物等通过新的方式联在一起,形成人与物、物与物相联,实现信息化、远程管理控制和智能化的网络。 2.物联网的组成 3.物联网应用举例智能家居 1物联网的数据源头 2物联的局域网络源头 1

    2024年02月05日
    浏览(55)
  • 数据结构和算法学习记录——平衡二叉树(基本介绍、平衡因子、平衡二叉树的定义、平衡二叉树的高度)

    目录 基本介绍 平衡因子 平衡二叉树  平衡二叉树的高度  什么是平衡二叉树? 以一个例子来解释一下: 搜索树结点按不同的插入次序,将会导致不同的深度和平均查找长度ASL   在二叉搜索树中查找一个元素:  (a)要找到Jan,需要查找一次;要找到Feb,需要查找两次;

    2023年04月26日
    浏览(50)
  • 【机器学习】处理样本不平衡的问题

    机器学习中,样本不均衡问题经常遇到,比如在金融风险人员二分类问题中,绝大部分的样本均为正常人群,可用的风险样本较少。如果拿全量样本去训练一个严重高准确率的二分类模型,那结果毫无疑问会严重偏向于正常人群,从而导致模型的失效,所以说,训练样本比例

    2024年02月14日
    浏览(29)
  • 【机器学习】处理不平衡的数据集

            假设您在一家给定的公司工作,并要求您创建一个模型,该模型根据您可以使用的各种测量来预测产品是否有缺陷。您决定使用自己喜欢的分类器,根据数据对其进行训练,瞧:您将获得96.2%的准确率!         你的老板很惊讶,决定使用你的模型,没有任何

    2024年02月11日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包