目录
例题:hdu 4585
Treap树
是一种简单的平衡二叉搜索树。
二叉搜索树的每一个节点都有一个键值,除此之外Treap树为每个节点人为添加了一个称之为优先级的权值。对于键值来说,这是一棵二叉搜索树,对于权值来说这是一个堆。
1、Treap树的唯一性
Treap树的重要特性:另每个节点的优先级互不相等,那么整棵树的形态时唯一的,和元素的插入顺序没有关系。
2、Treap树的平衡问题
树的形态依赖于节点的优先级,那么如何配置每个节点的优先级,才能避免二叉树的形态退化成链表?最简单的方法时把每个节点的优先级进行随机赋值,那么生成的Treap树形态也是随机的。这虽然不能保证每次生成的Treap树一定时平衡的,但是期望的插入、删除、查找的复杂度都是O(logn)的。
3、Treap树的数据结构
struct Node{
int size; // 以这个点为根的子树的节点的数量
int rank; // 优先级
int key; // 键值
Node *son[2]; //son[0]时左儿子,son[1]是右儿子
bool operator < (const Node &a)const {return rank < a.rank;}
int cmp(int x)const{
if(x == key) return -1;
return x < key? 0 : 1;
}
void update(){ //更新size
size = 1;
if(son[0] != NULL) size += son[0] -> size;
if(son[1] != NULL) size += son[1] -> size;
}
};
4、Treap树的插入
每读入一个新的节点,为它分配一个随机的优先级,插入到树中,在插入时动态调整树的结构,使它仍然是一棵Treap树。
把新节点插入到Treap树的过程有两步
(1)用朴素的插入方法把node按键值的大小插入到合适的子树上去。
(2)给node随机分配一个优先级,如果node的优先级违反了堆的性质,即它的优先级比父节点高,那么让node往上走,替代父节点,最后得到一个新的Treap树。
void insert(Node * &o, int x){ //插入
if(o == NULL){
o