Treap学习总结

Treap学习总结

 

    最近在研究平衡树,这里是我的treap学习笔记。

 

    Treap是一种用来排序的数据结构,编写比较容易,时间复杂度也很好。

 

Treap = Tree + Heap

为了解决查找树退化的问题,在所学的数据结构里,能保证树的层数尽量少,分布尽量均匀,我们最先想到的就是完全二叉树了。而具有完全二叉树性质的数据结构很明显,堆就是其中之一,所以我们可以试想一想,如果在满足二叉查找树的前提下,同时又能满足堆的性质,是不是就可以避免这个树的退化呢?

当然,如果都以权值作为标准的话,很明显是不可能做到的,但是我们可以再给每个节点添加一个修正值,让这个修正值构成,而原始值满足BST,这样就解决了二叉查找树的平衡问题了。

由于是一个学习总结,就不在描述treap的工作原理了,直接上代码了。

 

1,数据结构定义

1 struct node
2 {
3     int l,r;
4     int key,kind,fix;
5 }a[MaxN]; //Treap

 

2,左旋/右旋操作

 1 //左旋
 2 void turn_left(int &x)
 3 {
 4     int y=a[x].r;
 5 
 6     a[y].size=a[x].size;
 7     a[x].size-=a[a[rc].r].size+1;
 8     
 9     a[x].r=a[y].l;
10     a[y].l=x;
11     x=y;
12 }
13 //右旋
14 void turn_right(int &x)
15 {
16     int y=a[x].l;
17 
18     a[y].size=a[x].size;
19     a[x].size-=a[a[lc].l].size+1;
20     
21     a[x].l=a[y].r;
22     a[y].r=x;
23     x=y;
24 }
25 
26 //其中的size域存放的是以当前节点为根的子树上的节点个数,用来查找第K大值

 

3,插入操作

 1 //插入
 2 void insert(int &k,int tkey)
 3 {
 4     if (k==-1)
 5     {
 6         k=++tot;
 7         a[k].key=tkey;
 8         a[k].size=1;
 9         //memcpy(a[k].name,name,sizeof(name));
10         a[k].fix=rand();
11     }
12     else
13     if (tkey<a[k].key)
14     {
15         insert(a[k].l,tkey);
16         a[k].size++;
17         if (a[ a[k].l ].fix>a[k].fix)
18             turn_right(k);
19     }
20     else
21     {
22         insert(a[k].r,tkey);
23         a[k].size++;
24         if (a[ a[k].r ].fix>a[k].fix)
25             turn_left(k);
26     }
27     
28 }

 

4,删除操作

 1 void Delete(int &k,int tkey)
 2 {
 3     int lc=a[k].l; int rc=a[k].r;
 4     
 5     if (tkey==a[k].key) //找到要删除的节点 对其删除
 6     {
 7         if (lc==-1 || rc==-1) //情况一,该节点可以直接被删除
 8         {
 9             if (rc==-1) k=lc;        //用左子节点代替它
10             else k=rc;        //用右子节点代替它
11             flag=true;
12         }
13         else //情况二
14         {
15             if (a[lc].fix > a[rc].fix) //左子节点修正值较大,右旋
16             {
17                 turn_right(k);
18                 Delete(a[k].r,tkey); //修正子树
19                 if (flag) a[k].size--;
20             }
21             else  //左子节点修正值较小,左旋
22             {
23                 turn_left(k);
24                 Delete(a[k].l,tkey);
25                 if (flag) a[k].size--;
26             }
27         }
28     }
29     else 
30         if (tkey < a[k].key) {
31             Delete(a[k].l,tkey);  //在左子树查找要删除的节点
32             if (flag) a[k].size--;
33         }
34     else {
35         Delete(a[k].r,tkey); //在右子树查找要删除的节点
36         if (flag) a[k].size--;
37     }
38 }

 

5,查找操作[代码是用来查找第K大数的]

 1 int Search(int &now,int k)
 2 {
 3     int lc=a[now].l; int rc=a[now].r;
 4     if (k < a[lc].size + 1)  //左子树中查找排名第k的元素
 5         return Search(a[now].l,k);
 6     else if (k > a[lc].size + 1) //在右子树中查找排名第k-(a[lc]size+1)的元素
 7         return Search(a[now].r,k-(a[lc].size + 1));
 8     else
 9         return a[now].key; //返回当前节点
10 }

 

 

 

 

Treap的应用方面还是比较广的,最基本的应用就是查找元素排名和查找第K大值,所以可以用来动态的统计数据以及优化动态规划。

posted @ 2012-05-15 15:55  守護N1身边  阅读(214)  评论(0编辑  收藏  举报