一、数据结构概述
Treap是一种同时具备二叉搜索树(BST)和堆(Heap)性质的数据结构,通过随机优先级维护平衡性,实现高效的插入、删除和查询操作。
二、核心实现解析
- 节点结构:包含值(val)、计数(cnt)、子树大小(size)和随机优先级(priority)
- 旋转操作:左旋(rotateLeft)和右旋(rotateRight)维护堆性质
- 更新机制:update函数维护子树大小信息
- 六大核心操作:插入、删除、查排名、查值、前驱、后继
三、完整代码实现(带详细注释)
#include <iostream>
#include <cstdlib>
#include <climits>
using namespace std;
const int INF = 1e8; // 处理大数值范围
struct Node {
int val, size, cnt;
int priority;
Node *l, *r;
Node(int v) : val(v), size(1), cnt(1), l(nullptr), r(nullptr) {
priority = rand() % INF; // 随机优先级保证平衡
}
};
class Treap {
private:
Node *root;
// 更新节点子树大小
void update(Node *node) {
if(!node) return;
node->size = node->cnt;
if(node->l) node->size += node->l->size;
if(node->r) node->size += node->r->size;
}
// 左旋操作
void rotateLeft(Node *&node) {
Node *temp = node->r;
node->r = temp->l;
temp->l = node;
update(node);
update(temp);
node = temp;
}
// 右旋操作
void rotateRight(Node *&node) {
Node *temp = node->l;
node->l = temp->r;
temp->r = node;
update(node);
update(temp);
node = temp;
}
// 插入操作
void insert(Node *&node, int val) {
if(!node) {
node = new Node(val);
return;
}
if(val == node->val) {
node->cnt++; // 重复值计数
} else if(val < node->val) {
insert(node->l, val);
if(node->l->priority > node->priority)
rotateRight(node); // 维护堆性质
} else {
insert(node->r, val);
if(node->r->priority > node->priority)
rotateLeft(node); // 维护堆性质
}
update(node);
}
// 删除操作
void remove(Node *&node, int val) {
if(!node) return;
if(val < node->val) {
remove(node->l, val);
} else if(val > node->val) {
remove(node->r, val);
} else {
if(node->cnt > 1) {
node->cnt--; // 减少计数
} else {
if(!node->l || !node->r) {
Node *temp = node->l ? node->l : node->r;
delete node;
node = temp; // 单子树情况直接替换
} else {
// 选择优先级高的子树旋转
if(node->l->priority > node->r->priority) {
rotateRight(node);
remove(node->r, val);
} else {
rotateLeft(node);
remove(node->l, val);
}
}
}
}
if(node) update(node);
}
// 获取排名
int getRank(Node *node, int val) {
if(!node) return 0;
if(val < node->val) return getRank(node->l, val);
int leftSize = node->l ? node->l->size : 0;
if(val == node->val) return leftSize + 1;
return leftSize + node->cnt + getRank(node->r, val);
}
// 根据排名获取值
int getValue(Node *node, int rank) {
if(!node) return INF;
int leftSize = node->l ? node->l->size : 0;
if(rank <= leftSize) return getValue(node->l, rank);
if(rank <= leftSize + node->cnt) return node->val;
return getValue(node->r, rank - leftSize - node->cnt);
}
// 获取前驱
int getPre(Node *node, int val) {
if(!node) return -INF;
if(node->val >= val) return getPre(node->l, val);
return max(node->val, getPre(node->r, val));
}
// 获取后继
int getNext(Node *node, int val) {
if(!node) return INF;
if(node->val <= val) return getNext(node->r, val);
return min(node->val, getNext(node->l, val));
}
public:
Treap() : root(nullptr) { srand(time(0)); }
// 公开接口
void insert(int val) { insert(root, val); }
void remove(int val) { remove(root, val); }
int getRank(int val) { return getRank(root, val); }
int getValue(int rank) { return getValue(root, rank); }
int getPre(int val) { return getPre(root, val); }
int getNext(int val) { return getNext(root, val); }
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
Treap treap;
int n, opt, x;
cin >> n;
while(n--) {
cin >> opt >> x;
switch(opt) {
case 1: treap.insert(x); break;
case 2: treap.remove(x); break;
case 3: cout << treap.getRank(x) << '\n'; break;
case 4: cout << treap.getValue(x) << '\n'; break;
case 5: cout << treap.getPre(x) << '\n'; break;
case 6: cout << treap.getNext(x) << '\n'; break;
}
}
return 0;
}
四、实际应用场景
- 动态排名系统
- 数据库索引
- 游戏排行榜
- 实时数据分析
五、学习建议
- 先理解BST和堆的基本原理
- 手动模拟小规模数据操作
- 尝试实现其他平衡树如AVL、红黑树
- 练习相关题目巩固理解
来源:洛谷题解