二叉查找树和笛卡尔树

news/2024/10/18 21:25:16/文章来源:https://www.cnblogs.com/meteor2008/p/18474364

目录
  • 二叉查找树
    • 定义
    • 作用
    • 操作
      • 查找
      • 插入
      • 删除
    • 缺点
  • 笛卡尔树
    • 定义
    • 操作
      • 构造

二叉查找树

定义

二叉查找树(Binary Search Tree,BST),又名二叉搜索树或二叉排序树。

​ 它是一类特殊规定的二叉树,它应当满足以下条件:

  1. 每个节点有唯一确定的权值
  2. 非叶子节点的权值比其左子树中所有节点权值大
  3. 非叶子节点的权值比其右子树中所有节点权值小

​ 由于上述特性,易知BST的中序遍历是一个有序排列。

​ 特别地,空树也是一棵BST(觉得有意思就记下来了?)

作用

​ 顾名思义,它用于快速地查找数据,同时它也支持快速地插入删除数据。

​ 因为在BST上查找一个数,所需的查找次数不超过树的深度。查找过程类似于二分,运气好的话,它的时间复杂度能和二分相同。

​ 实际上,由于原序列本身无序,所以每次查找的时间复杂度会在\(O(\log n)\)\(O(n)\)之间浮动。(具体原因后面再写)

操作

查找

​ 通过递归实现。

​ 二分思想中,每一次会在区间[l,r]中取mid,将区间均分为两半。并对mid进行检查,以此决定接下来是查找左区间还是右区间。

(说起来,初中数学有教过二分吧?)

​ 对应的,在BST中,当前查找到的节点相当于区间的mid,将区间分为左子树和右子树两部分(遗憾的是,并非均分)。对当前节点进行“判断”,就可以决定接下来的查找范围是枣子树还是柚子树。

(好耶,是枣子柚子二选一!)

(试图把左子树称为枣子树,把右子树称为柚子树)

插入

​ 在查找操作的基础上加一点点东西。

​ 如果按照给定顺序和值(即给定序列)插入,最终建成的BST一定是唯一的。

​ 对于需要插入的数据,我们可以通过查找得到它“应该在的位置”。如果这个位置是空位,就在这个位置插入新节点。

(如果不是空位,说明之前已经有同样的数据,可以按照需要进行记录。例如在每个节点用int cnt记录数据出现次数)

删除

​ 有删除操作时,BST可能不唯一。

​ 好在有两种轻松愉悦的情况:

​ 1.如果要删除的节点孤苦伶仃,无儿无女,无依无靠,那直接把它删了就行,反正也没节点给它收尸不是吗。

​ 2.如果要删除的节点只有枣子树或只有柚子树(总之就是只有一个儿子),那么直接删除它,并将子树衔接上来,代替它的位置。

​ 其余情况比较麻烦(儿孙们要争夺祖父的地位(?)

​ 这里列举两种常见的解决方法,同样是递归操作:

​ 其一是:用左子树中的最大节点,顶替删除节点。但是对于左子树来说,这相当于删除了“最大节点”,所以继续递归,直到前面两种情况之一。

​ 其二是:用右子树中的最小节点,顶替删除节点。同理,继续递归。

​ 由于删除时的操作,BST可能变成奇奇怪怪的形状。

缺点

形态不稳定。

​ 前面有说过,它每次操作的时间复杂度最好是\(O(\log n)\),最差会到\(O(n)\)。这是因为插入序列的顺序不一定,按照它建出的BST可能恰好平衡,也可能退化成一条链。

​ 比如序列4213657是一棵满二叉树:Annotation 2023-03-25 105753

​ 而序列1234567就会退化成一条链:Annotation 2023-03-25 110026

​ 此外,在删除的过程中,还会改变树的形态,也可能会使它退化。

​ BST存在的问题即“如何保持平衡的形态”。后续的替罪羊树、Treap树、Splay树、红黑树等等都是基于“维护平衡”这一问题的BST树优化算法。

笛卡尔树

定义

笛卡尔树是一类特殊的二叉查找树,其和一般BST的区别在于每个节点包括两个权值信息。

一棵笛卡尔树应当满足如下条件:

  1. 每个节点包括两个唯一确定的权值\((x_u,y_u)\)
  2. 只考虑权值\(x_u\)的情况下,树的形态应当符合一棵二叉查找树的性质。
  3. 只考虑权值\(y_u\)的情况下,树的形态应当符合大根堆或小根堆的性质。

根据OI Wiki的说明,如果一棵笛卡尔树的\((x_u,y_u)\)唯一确定,那么这棵笛卡尔树的形态唯一

关于唯一确定:即\((x_u,y_u)\)均已知,且\(x_u\)互不相同,\(y_u\)互不相同。

操作

构造

首先将节点按照\(x_u\)从小到大的顺序排序,现在假设我们要构造的笛卡尔树符合小根堆的性质。

由于二叉查找树的性质,且\(x_u\)递增,显然新节点的位置应该尽可能靠右。可以通过维护从根开始的一条极长链,满足每个节点都是其父节点的右儿子。

这条链满足链上节点的权值\(x,y\)均单调递增,可以看作一个单调栈,或者说可以用单调栈来维护。加入新节点\(u\)的时候,在链上找到深度最大的节点\(v\)满足\(y_v<y_u\),将其作为\(u\)的父节点。显然\(x_u>x_v\),故令\(u\)\(v\)的右儿子。

如果\(v\)有右儿子,则将\(v\)的右子树拆下来,接在\(u\)的左子树下。由于\(v\)是深度最大的\(y<y_u\),所以\(y_v<y_u<y_{rs(v)}\),且\(x_u>x_{rs(v)}\),所以这样操作不会破坏笛卡尔树的性质。

以洛谷P5854【模板】笛卡尔树为例,代码如下:

#include <bits/stdc++.h>
using namespace std;
#define lld long longconst int N = 1e7+5;
int n, q[N], tl = 0;
struct Tree{int val, ls, rs;
}t[N];void read(int &x){char input = getchar(); x = 0;while(input<'0'||input>'9')input = getchar();while(input>='0'&&input<='9'){x = x*10+(input-'0');input = getchar();}
}int main(){scanf("%d", &n);for(int i = 1; i <= n; i++){int T = tl; read(t[i].val);while(tl && t[q[tl]].val > t[i].val) tl--;if(tl) t[q[tl]].rs = i;if(tl < T) t[i].ls = q[tl+1];q[++tl] = i;}lld ans1 = 0, ans2 = 0;for(int i = 1; i <= n; i++){ans1 ^= (lld)i*(t[i].ls+1);ans2 ^= (lld)i*(t[i].rs+1);} printf("%lld %lld\n", ans1, ans2);return 0;
} // 此题的恶心之处在于必须快读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/817066.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈 tarjan

就是记录两个数组:dfn[]和low[] 其中dfn[]表示访问的顺序,low[u]用来存储 \(u\) 不经过其父亲能到达的最小时间戳。。。 搬一下 wiki 的图。。。我们发现 \(low[v]\ge dfn[u]\) 可以表示不能回到祖先,则 \(u\) 点位割点。。。 直接上代码P3388------> #include <bits/…

正点原子新起点V2开发板FPGA关于SDRAM代码解读

正点原子新起点V2开发板FPGA关于SDRAM代码解读 1. SDRAM 概述 SDRAM(Synchronous Dynamic Random Access Memory)是一种同步动态随机存储器,广泛用于FPGA项目中。通过SDRAM控制模块,可以实现数据读写、刷新等操作。本文对SDRAM的控制模块进行详细解读,分析代码中的命令控制…

面试题速刷 - 实战会碰到的一些问题

页面如何进行首屏优化?路由懒加载服务端渲染SSR只获取HTML就可以,里面包含data。 APP预取(啥东西)APP结合H5、结合JS bridge 分页图片懒加载 lazyloadHybrid总结:后端一次性返回10w条数据,你会如何渲染? 本身后端设计方案的设计就不合理!非要的话......自定义中间层:虚…

氏发

这个作业属于哪个课程 2024高级语言程序设计 (福州大学 - 计算机与大数据学院)这个作业要求在哪里 高级语言程序设计课程第三次个人作业学号 102400117姓名 廖逸轩

二、STM32F103C8T6-定时器

STM32F103C8T6 定时器概述 STM32F103C8T6 作为一款广泛使用的微控制器,内置多个定时器,能够支持多种计时和控制功能,如精确延时、脉冲宽度调制(PWM)、捕获比较(Capture/Compare)、输入捕获 和 输出比较 等。这些功能在电机控制、信号测量、周期性事件触发等应用中非常常…

Sparse Table

Sparse Table 可用于解决这样的问题:给出一个 \(n\) 个元素的数组 \(a_1, a_2, \cdots, a_n\),支持查询操作计算区间 \([l,r]\) 的最小值(或最大值)。这种问题被称为区间最值查询问题(Range Minimum/Maximum Query,简称 RMQ 问题)。预处理的时间复杂度为 \(O(n \log n)\…

计量经济学(十一)——联立方程模型的估计

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 联立方程模型(Simultaneous Equations Model, SEM)是一类包含多个相互依赖变量的统计模型,用来描述这些变量之间的相互关系。在传统的单一方程模型中,通常…

数据结构与算法 课程随记

数据结构与算法 课程随记因为有时候需要在不同设备编辑同一份文档,本地不太方便了,先在放着博客园比较省事吧。 但是博客园是不是快要四了啊,没事再整一个个人博客吧。 Class https://www.runoob.com/cplusplus/cpp-classes-objects.html大纲 定义成员函数,(无论public/pri…

pve安装后删除local-lvm并把其空间全部分给local

在安装pve的时候,系统默认分配给local的空间非常小,我们可以通过以下方法把local-lvm删除,并将其空间还给local。 在webui的pve节点的磁盘选项中找到LVM-Thin,删除data卷。删除后此处为空。 接着打开终端执行以下命令: lvresize --extents +100%FREE --resizefs pve/root此…

PYNQ Z2 读取xadc外部通道电压

使用XADC 或者JTAG只能读取XADC的内部电压, 而无法读取外部通道的电压 现在使用xsysmon.h库里面的函数进行XADC外部通道的电压 为了方便观察,增加了PL GPIO KEY LED进行观察 1. 配置ZYNQ70002.添加两个axi gpio并进行配置 AXI GPIO0AXI GPIO13. 添加XADC进行配置 这里选择axi l…

10.18 模拟赛

炼石计划 10 月 04 日 NOIP 模拟赛 #8【补题】 - 比赛 - 梦熊联盟 (mna.wang) 复盘 T1 有种 div.2 B 的风格,没秒,想看题。 T2。只判是否无解?\(k \le 100\)?把 \(200\) 个关键连通块拿出来建图跑传递闭包不就做完了。 一遍过大样例?简直不可思议,但还是把 T2 关了吧。 用…

小心!这样分享 B 站视频会暴露身份

已经有被开盒的案例了。‍ 在 2022 年 6 月 10 日 0 点,B 站在视频的网址上加了个参数 ?vd_source=XXXXXXXXXXXXXXX​,如图: ​ 经过网友的测试,这个参数值很可能就是用户 ID 的 hash 值(简单来说就是用户身份),所以如果直接复制网址的话,是有可能被“开盒”的。 ‍ 其…