前言
其實我寫過旋轉的Treap,我也寫過可以旋轉不停的Splay
但是我發現Splay克我,所以我學了一下神奇的非旋Treap
效率並不低,效率較低的部分在insert,要調用4次 O(log2n) O ( l o g 2 n ) 的函數
其他操作或1次或2次
表現較好在我們學習之前我們可能需要一些關於旋轉Treap的知識
帶旋轉Treap
本文並不是講述帶旋轉Treap的文章,但是非旋Treap需要借用它的一些思想
畢竟都是Treap
Treap=Tree+Heap
就是一棵具有堆性質的二叉搜索樹
二叉搜索樹性質體現在權值上,左兒子權值小與父親權值,右兒子權值大於父親權值
堆體現在我們再隨機出一些附加值,使得每個點的附加值像堆一樣,父亲的優先度高於兒子
由於堆是完全二叉樹,所以可以使得Treap接近平衡
其維護堆性质的方法就是rotate,rotate,rotate,一旦破壞該性質就rotate,使得Treap像是一顆完全二叉樹
非旋Treap
struct node
{
node *son[2];
int val,key,size;
inline void push_up(){size=son[0]->size+son[1]->size+1;}
node(const int &x);
}*nil=new node(0),*Root=nil;
node::node(const int &x)
{
size=1;//不要忘了到時候把nil的size清零,否則你會爆零//Root也要清
val=x;
key=Random();
son[0]=son[1]=nil;
}
非旋Treap借用了Treap的堆的概念,在二叉搜索樹基礎上維護了一個堆
原理是一樣的,但是他不通過rotate來維護,而是通過神奇的
Split和Merge S p l i t 和 M e r g e
超神奇,還免去了大量的討論,使得代碼長度可觀了許多
這兩個操作非常重要先講述一下 Merge M e r g e
這裡會用到