reap 是一種平衡樹。Treap 發音爲[ ]。這個單詞的構造選 取了 Tree(樹)的前兩個字符和 Heap(堆)的後三個字符,Treap = Tree + Heap。顧名思義,Treap 把 BST 和 Heap 結合了起來。它和 BST 一樣滿足許多優美的性質,而引入堆目的就是爲了維護平衡。
以上是基本的介紹,具體一點是這樣,Treap 可以定義爲有以下性質的二叉樹:
1. 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值,而且它的根節點 的修正值小於等於左子樹根節點的修正值;
2. 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值,而且它的根節點 的修正值小於等於右子樹根節點的修正值;
3. 它的左、右子樹也分別爲 Treap。
Treap的維護主要是通過左旋和右旋實現的,爲了把左孩子或者右孩子變成父親,具體是這樣操作。
來舉個例子,如圖所示的左邊的一個 Treap,它仍然滿足 BST 性質。但是由於某些原因,節點 4 和節點 2 之間不滿足最小堆序,4 作爲 2 的父節點,它的修正值大於左子節點的修正值。我們只有 將 2 變成 4 的父節點,才能維護堆序。根據旋轉的性質我們可以知道,由於 2 是 4 的左子節 點,爲了使 2 成爲 4 的父節點,我們需要把以 4 爲根的子樹右旋。右旋後,2 成爲了 4 的父 節點,滿足堆序。
Insert和Delete操作都和BST和HEAP很像,具體看代碼咯。
struct Treapnode
{
Treapnode *left,*right;
int value,fix;
};
Treapnode *root;
void Treapleft(Treapnode *&a)
{
Treapnode *b=a->right;
a->right=b->left;
b->left=a;
a=b;
}
void Treapright(Treapnode *&a)
{
Treapnode *b=a->left;
a->left=b->right;
b->right=a;
a=b;
}
Treapnode *Treapfind(Treapnode *p,int value)
{
if(!p)
return 0;
if(p->value==value)
return p;
if(p->value<value)
return Treapfind(p->left,value);
else
return Treapfind(p->right,value);
}
void Treapprint(Treapnode *p)
{
if(p)
{
Treapprint(p->left);
printf("%d",p->value);
Treapprint(p->right);
}
}
void Treapinsert(Treapnode *&p,int value)
{
if(!p)
{
p=new Treapnode;
p->value=value;
p->fix=rand();
}
else
{
if(value<=p->value)
{
Treapinsert(p->left,value);
if(p->left->fix<p->fix)
Treapright(p);
}
else
{
Treapinsert(p->right,value);
if(p->right->fix<p->fix)
Treapleft(p);
}
}
}
void Treapdelete(Treapnode *&p,int value)
{
if(p->value==value)
{
if(!(p->left) || !(p->right))
{
Treapnode *t=p;
if(p->left)
p=p->left;
else
p=p->right;
delete t;
}
else
{
if(p->left->fix<p->right->fix)
{
Treapright(p);
Treapdelete(p->right,value);
}
else
{
Treapleft(p);
Treapdelete(p->left,value);
}
}
}
else
{
if(value<p->value)
Treapdelete(p->left,value);
else
Treapdelete(p->right,value);
}
}