平衡树

1|0Treap

Treap 是既满足二叉搜索树的性质又满足堆性质的树。它通过随机优先级实现树高在 O(log(n)) 级别。以下是两种实现 Treap 的方式。

2|0旋转 Treap

3|0非旋 Treap

又称 FHQ-Treap。
原理:将要修改的部分分裂出来,修改,然后合并。

3|1分裂

void split(int k, int id, int &p, int &q){ if(!id){ p = q = 0; return; } pd(id); if(tr[tr[id].ls].sz >= k){ //左子树在p中 split(k, tr[id].ls, p, tr[id].ls); q = id; } else{ //右子树在q中 split(k - tr[tr[id].ls].sz - 1, tr[id].rs, tr[id].rs, q); p = id; } pp(id); }

3|2合并

int merge(int p, int q){ if(!p || !q) return p + q; if(tr[p].p > tr[q].p){ //p当根 pd(p); tr[p].rs = merge(tr[p].rs, q); pp(p); return p; } else{ //q当根 pd(q); tr[q].ls = merge(p, tr[q].ls); pp(q); return q; } }

4|0splay

splay 有一字旋和之字旋。
可以证明,其时间复杂度是 O(log2n)

4|1旋转函数

void rotate(int x){ int y = tr[x].fa, z = tr[y].fa, k = (tr[y].s[1] == x); pd(x); pd(y); tr[z].s[tr[z].s[1] == y] = x, tr[x].fa = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].fa = y; tr[x].s[k ^ 1] = y, tr[y].fa = x; pp(y); pp(x); }

4|2核心函数

void splay(int x, int k){ //把x旋转到k下面 while(tr[x].fa != k){ int y = tr[x].fa, z = tr[y].fa; if(z != k){ if((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x); else rotate(y); } rotate(x); } if(!k) root = x; }

5|0易错点

1 一个点的 sz 要设为 1, pushup 时要 sz 时左右孩子之和加 1


__EOF__

本文作者louisliang
本文链接https://www.cnblogs.com/louisliang/articles/17929332.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   louisliang  阅读(9)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示