笛卡尔树学习笔记
这种数据结构并不常用,但有时候对简化思维和优化复杂度有一定的帮助。
简介#
笛卡尔树是一个二叉树,每一个节点由两个键值构成,(k,w) 其中,k 满足二叉搜索树的性质,w 满足二叉堆的性质,
如果给定数组 a,以数组下标作为 k,用数组里面存放的值作为 w,则不难发现这个笛卡尔树的性质,一棵子树内的下标对应一段连续的区间,当然我们建立笛卡尔树不能只是对数组建立,这样具有一定的特殊性,我们要对于任意的二元组建立笛卡尔树。
构建#
对任意二元组建立笛卡尔树的方法如下:
-
首先,我们将所有的二元组按照 k,也就是第一关键字来排序。
-
我们定义 右链 为从根节点开始,如果有右儿子就一直走下去,走过的点形成的链。
我们考虑这样 增量 来构造笛卡尔树,设当前的二元组为 (a,b)。
-
我们从右链的最低端开始遍历,设当前遍历的二元组为 (c,d),如果我们有 b<d 那么就停止遍历,将插入点设置为当前遍历的 右 子树,把插入点的左子树设置为当前遍历点以前的右儿子。
考虑正确性证明:
- 首先关注到 k 是有序的,因为我们是把当前遍历点设置为插入点的 左 子树,所以这样显然满足二查搜索树性质,又因为我们是遍历到有 b<d 的时候才插入,所以很显然这棵树的第二关键字也满足堆的性质。
考虑复杂度证明:
- 首先显然,如果一个当前插入点遍历到了一个点却没有选择插入,那么这个点以后就不会存在在右链之中,也就是说,每个点仅会被最多 经过 一次,所以复杂度是均摊 O(n)。
考虑实现,我们可以用栈来模拟右链,插入代码如下:
inline void Insert(int k){
int Last=Top;
while(W[Stack[Last]]>W[k]) Last--;
ls[k]=rs[Last]
rs[Last]=k;
Stack[++Last]=k;
Top=k;
}
注意,以上实现仅供参考,正确性并不保证。可能会有所修改。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理