Treap,是有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。
Treap=Tree+Heap。Treap本身是一棵二叉搜索树,它的左子树和右子树也分别是一个Treap,和一般的二叉搜索树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉搜索树的同时,还满足堆的性质。Treap维护堆性质的方法用到了旋转,只需要两种旋转,编程复杂度比Splay要小一些。
插入
给节点随机分配一个优先级,先和二叉搜索树的插入一样,先把要插入的点插入到一个叶子上,然后跟维护堆一样,如果当前节点的优先级比根大就旋转,如果当前节点是根的左儿子就右旋如果当前节点是根的右儿子就左旋。
由于旋转是O(1)的,最多进行h次(h是树的高度),插入的复杂度是O(h)的,在期望情况下h=O(logn),所以它的期望复杂度是O(logn)。
删除
因为Treap满足堆性质,所以只需要把要删除的节点旋转到叶节点上,然后直接删除就可以了。具体的方法就是每次找到优先级最大的儿子,向与其相反的方向旋转,直到那个节点被旋转到了叶节点,然后直接删除。
删除最多进行O(h)次旋转,期望复杂度是O(logn)。
查询
和一般的二叉搜索树一样,但是由于Treap的随机化结构,Treap中查找的期望复杂度是O(logn)。
代码(一种递归实现):
#include <iostream>
#include <iomanip>
#include <queue>
#include <cstdlib>
using namespace std;
typedef struct TreapNode * Treap;
typedef struct TreapNode
{
int data;
int priority;
Treap lchild,rchild;
} TreapNode;
#define Infinity 0x7FFFFFFF
Treap NullNode = NULL;
Treap Initialize(void)
{
if (NullNode == NULL)
{
NullNode = new TreapNode;
NullNode->priority = Infinity;
NullNode->lchild = NullNode->rchild = NullNode;
}
return NullNode;
}
Treap SingleRotateWithLeft(Treap x)
{
Treap y = x->lchild;
x->lchild = y->rchild;
y->rchild = x;
return y;
}
Treap SingleRotateWithRight(Treap x)
{
Treap y = x->rchild;
x->rchild = y->lchild;
y->lchild = x;
return y;
}
Treap insert(int key, Treap T)
{
if (T == NullNode) {
/* create and return an one-node tree */
T = new TreapNode;
T->data = key;
T->priority = rand();
T->lchild = T->rchild = NullNode;
}
else
{
if (key < T->data) {
T->lchild = insert(key, T->lchild);
if (T->lchild->priority < T->priority) {
T = SingleRotateWithLeft(T);
}
}
else if (key > T->data) {
T->rchild = insert(key,T->rchild);
if (T->rchild->priority < T->priority) {
T = SingleRotateWithRight(T);
}
}
}
return T;
}
Treap remove(int key, Treap T)
{
if (T != NullNode)
{
if (key < T->data) {
T->lchild = remove(key,T->lchild);
}
else if (key > T->data) {
T->rchild = remove(key,T->rchild);
}
else {
/*match found*/
if (T->lchild->priority < T->rchild->priority)
T = SingleRotateWithLeft(T);
else
T = SingleRotateWithRight(T);
if (T != NullNode) /* continue go down*/
T = remove(key,T);
else
{
/* at a leaf*/
delete (T->lchild);
T->lchild = NullNode;
}
}
}
return T;
}
/*------------------about tree display -----------------------------------------*/
inline int max(int a,int b)
{
return a>b?a:b;
}
int Height(Treap T)
{
if (T == NullNode)
return 0;
else
return 1 + max(Height(T->lchild), Height(T->rchild));
}
void MakeMat(Treap T,int root_x,int root_y,int step,int **m)
{
int lChildPos,rChildPos;
lChildPos = root_x - step;
rChildPos = root_x + step;
if (T == NullNode)
return;
else
{
m[root_y][root_x] = 1;
MakeMat(T->lchild,lChildPos,root_y+1,step>>1,m);
MakeMat(T->rchild,rChildPos,root_y+1,step>>1,m);
}
}
void TreapDisplay(Treap T)
{
if(T == NullNode)
return;
/* init placehold flags m[h][len] */
int h = Height(T);
int len = (1<<h) - 1;
int row = h;
int **m = new int*[row];
for(int i= 0;i<row;i++){
m[i] = new int[len];
memset(m[i],0,len*sizeof(int));
}
/* get level order traversal sequence */
vector<Treap> v;
queue<Treap> q;
queue<Treap> qt;
q.push(T);
Treap pt;
while(!q.empty())
{
pt = q.front();
if (pt->lchild != NullNode)
q.push(pt->lchild);
if(pt->rchild != NullNode)
q.push(pt->rchild);
v.push_back(pt);
q.pop();
}
/* generate output matrix plus '/' and '\\' m[2*h-1][len] */
MakeMat(T,len>>1,0,len+1>>2,m);
/* generate output */
int cnt = 0;
int width = 1;
for(int i = 0; i < row; i++)
{
for(int j = 0; j < len; j++)
{
if(m[i][j])
{
// if (i & 1)
// cout<<setw(width)<<char(m[i][j]);
// else
// cout<<setw(width)<<char(m[i][j]);
// cout<<setw(width)<<m[i][j];
cout<<(v[cnt])->data;
cnt++;
}
else
cout<<setw(width)<<' ';
}
cout<<endl;
}
}
/*-------------- I am a cut-----------------------------------------------------*/
int main()
{
NullNode = Initialize();
Treap T = NullNode;
int i;
for (i = 1; i <= 7 ; i++)
{
cout<<"Key = "<<i<<" inserting :"<<endl;
T = insert(i,T);
TreapDisplay(T);
cout<<"------------------------------------------"
"--------------------------"<<endl;
}
for( i = 1;i <= 7; i++)
{
cout<<"Key = "<<i<<" deleting :"<<endl;
T = remove(i,T);
TreapDisplay(T);
cout<<"------------------------------------------"
"--------------------------"<<endl;
}
}
代码输出:
Key = 1 inserting :
1
--------------------------------------------------------------------
Key = 2 inserting :
1
2
--------------------------------------------------------------------
Key = 3 inserting :
1
3
2
--------------------------------------------------------------------
Key = 4 inserting :
1
3
2 4
--------------------------------------------------------------------
Key = 5 inserting :
1
3
2 5
4
--------------------------------------------------------------------
Key = 6 inserting :
1
3
2 6
5
4
--------------------------------------------------------------------
Key = 7 inserting :
1
3
2 7
6
5
4
--------------------------------------------------------------------
Key = 1 deleting :
3
2 7
6
5
4
--------------------------------------------------------------------
Key = 2 deleting :
3
7
6
5
4
--------------------------------------------------------------------
Key = 3 deleting :
7
6
5
4
--------------------------------------------------------------------
Key = 4 deleting :
7
6
5
--------------------------------------------------------------------
Key = 5 deleting :
7
6
--------------------------------------------------------------------
Key = 6 deleting :
7
--------------------------------------------------------------------
Key = 7 deleting :
--------------------------------------------------------------------
REF:
1,http://zh.wikipedia.org/wiki/Treap
2,数据结构与算法分析-C语言描述