[平衡树]旋转Treap实现平衡树

本文介绍了Treap这种结合了树和堆特性的数据结构,用于解决二叉搜索树平衡问题。通过旋转(右旋、左旋)操作和随机优先级保持树的平衡,同时讲解了插入、删除、查询排名、查询特定数值及其前驱和后继的操作。文章以C++代码实现,并举例说明。
摘要由CSDN通过智能技术生成

写在前面

首先你需要了解 二叉搜索树(百度链接)。
这就是一个标准的二叉搜索树,是一颗满二叉树
示意图
很好,树高 l o g n log n logn ,查询的复杂度也就是 l o g n log n logn
但是总有 毒瘤 的出题人卡数据,把你的树卡成链
实体图
查询复杂度为 n n n,这肯定不行啊,时间复杂度跟暴力一样了,怎么才能把树造的平衡一点呢。

正文

Treap 的由来是 Tree + Heap 既是一棵树,又有堆的性质,所以我们有时候叫他树堆

目的

因为一组数据 可以造很多种各不相同的二叉搜索树,所以 一条链的树 可以通过 变换形态 在 本质不变(中序遍历不变)的情况下变成一棵 平衡二叉树。

这时候可以加入一个 随机优先级(本文用 rd 表示)(一般用随机数),用堆的形式来 维护

如何操作呢???

操作

如何维护优先级呢???

旋转

旋转

旋转分两种,右旋 和 左旋

右旋

当优先级不满足时,如下图
(规定优先级大的放上面)

示意图
如图可知,D的根节点 < B < E的根节点 < A < C 的根节点 (二叉搜索树的性质,此处比的是节点的值的大小,不是优先级!)

但是 B的优先级 比 A的优先级 大,怎么才能让B旋上去呢???
根据二叉搜索树的性质,右旋后的树 应该满足
D的根节点 < B < E的根节点 < A < C 的根节点,
所以应该长这样

右旋后 :
示意图
满足了
D的根节点 < B < E的根节点 < A < C 的根节点,

可以观察发现
A的左儿子 变成了 树根,
B的右儿子 变成了 A,
A的左子树 变成了 E树,
B树 的节点数 变成了 A树 的节点数
A树 的节点数 变成了 E树节点数 + C树节点数

代码实现 :

void rturn (int &now) {
   //右旋,左节点上移 
 int p = t[now].l;
 t[now].l = t[p].r;//A的左子树变成E树
 t[p].r = now;//树根(B)的右儿子变成A
 t[p].sz = t[now].sz;//B树 的节点数 变成了 A树 的节点数
 update (now);//A树 的节点数 变成了 E树节点数 + C树节点数
 now = p;//B成为树根
 return ;
}

演示一遍
1
2

3

4

5
6
7
8

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值