具有随机性的平衡树——treap
简而言之,treap=tree+heap,首先它是一棵二叉树,其次treap中每个节点含有一个优先级的值,这些值随机给定,但整棵树中的这些值满足大根堆(或小根堆的性质)。
左旋与右旋操作跟其他平衡树一样。
插入操作:首先将新节点插入到叶子节点位置(与普通排序二叉树一样),然后由于插入后可能破坏了heap的性质,这个时候需要对新插入节点的根节点进行左旋或右旋,一直调整到符合heap性质为止。
删除操作:将需要删除的节点旋转到叶子节点或者只有一个孩子的位置,然后删掉就可以了。
关于size,用treap来维护节点的size域(即以某节点为根的子树中节点的个数)是非常方便的,加一个maintain操作即可。
// 不带size域的treap class Treap { public: const static int MaxN = 100000; int root, tsize, l[MaxN], r[MaxN], p[MaxN]; int key[MaxN]; void rot_l(int &x) { //before using this function, please ensure that the right son of x exist int tmp = r[x]; r[x] = l[tmp]; l[tmp] = x; x = tmp; } void rot_r(int &x) { //before using this function, please ensure that the left son of x exist int tmp = l[x]; l[x] = r[tmp]; r[tmp] = x; x = tmp; } Treap():root(-1),tsize(-1) {} void insert(int &root, const int &x) { if(root == -1) { key[++tsize] = x; root = tsize; p[root] = rand(); l[root] = r[root] = -1; } else if(x <= key[root]) { insert(l[root], x); if(p[l[root]] > p[root]) rot_r(root); } else { insert(r[root], x); if(p[r[root]] > p[root]) rot_l(root); } } void del(int &root, const int &x) { if(key[root] == x) { if(l[root]==-1 && r[root]==-1) root = -1; else if(l[root] == -1) root = r[root]; else if(r[root] == -1) root = l[root]; else { if(p[l[root]] > p[r[root]]) { rot_r(root); del(r[root], x); } else { rot_l(root); del(l[root], x); } } } else if(x < key[root]) del(l[root], x); else del(r[root], x); } bool find(int &root, const int &x) { if(root == -1) return false; if(x == key[root]) return true; else if(x < key[root]) return find(l[root], x); else return find(r[root], x); } };
//带size的treap class Treap { public: const static int MaxN = 100000; int root, tsize, l[MaxN], r[MaxN], p[MaxN], nsize[MaxN]; int key[MaxN]; void maintain(const int &root) { int ta, tb; ta = l[root]==-1? 0 : nsize[l[root]]; tb = r[root]==-1? 0 : nsize[r[root]]; nsize[root] = ta+tb+1; } void rot_l(int &x) { //before using this function, please ensure that the right son of x exist int tmp = r[x]; r[x] = l[tmp]; maintain(x); l[tmp] = x; x = tmp; maintain(x); } void rot_r(int &x) { //before using this function, please ensure that the left son of x exist int tmp = l[x]; l[x] = r[tmp]; maintain(x); r[tmp] = x; x = tmp; maintain(x); } Treap():root(-1),tsize(-1) {} void insert(int &root, const int &x) { if(root == -1) { key[++tsize] = x; root = tsize; p[root] = rand(); l[root] = r[root] = -1; nsize[root] = 1; } else if(x <= key[root]) { insert(l[root], x); if(p[l[root]] > p[root]) rot_r(root); } else { insert(r[root], x); if(p[r[root]] > p[root]) rot_l(root); } maintain(root); } void del(int &root, const int &x) { if(key[root] == x) { if(l[root]==-1 && r[root]==-1) root = -1; else if(l[root] == -1) root = r[root]; else if(r[root] == -1) root = l[root]; else { if(p[l[root]] > p[r[root]]) { rot_r(root); del(r[root], x); } else { rot_l(root); del(l[root], x); } } } else if(x < key[root]) del(l[root], x); else del(r[root], x); if(root != -1) maintain(root); } int kthElement(const int &root, int k) { int ta; ta = l[root]==-1? 0 : nsize[l[root]]; if(ta >= k) return kthElement(l[root], k); else if(ta+1 == k) return key[root]; else return kthElement(r[root], k-ta-1); } bool find(int &root, const int &x) { if(root == -1) return false; if(x == key[root]) return true; else if(x < key[root]) return find(l[root], x); else return find(r[root], x); } };