文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>treap

treap

时间:2010-11-11  来源:forever zsz

首先是插入:插入这列基本与裸的TREAP一样,只需要加两句话即可:

void insert(int &x,int y)//注意x前面的&。
{
     if (x==0)
     {
              x=++size;
              e[x].l=0;e[x].r=0;e[x].a=y;e[x].ll=0;e[x].rr=0;
              e[x].b=rand()*rand();
              return;
     }
     if (y>e[x].a)
     {
                  e[x].rr++;//如果大于X的话,则x的右儿子个数++;
                  insert(e[x].r,y);
                  if (e[x].b>e[e[x].r].b) right(x);
                  return;
     }
     if (y<=e[x].a)
     {
                   e[x].ll++;//同理,如果小于x的话,则X的左儿子个数++;
                   insert(e[x].l,y);
                   if (e[x].b>e[e[x].l].b) left(x);
                   return;
     }
}

下面就是treap的旋转:

其实只要正确理解旋转的定义就可以了.下面就以右旋为例(其实左右旋到底哪个是哪个我也不是很清楚,不过只要记住操作就可以了)

在右旋中,因为右儿子的随机关键字小于父节点(这里以小根堆为例),因此需要执行旋转.

由图上的旋转可知,旋转后x(要旋转的节点)的右节点(下面称J),J的左儿子变成了X的右儿子,因此E[X].RR=E[J].LL;

而J的左儿子,变成了X+X左儿子+J左儿子;

因此,只要如下面代码那样就可以实现了;

void right(int &x)
{
     int j=e[x].r;
     e[x].r=e[j].l;
     e[x].rr=e[j].ll;//
     e[j].l=x;
     e[j].ll=e[x].ll+e[j].ll+1;
     x=j;
}

 最后是最复杂的Delete操作:

有了旋转的操作之后,Treap的删除比BST还要简单。因为Treap满足堆性质,所以我们只需要把要删除的节点旋转到叶节点上,然后直接删除就可以了。具体的方法就是每次找到优先级最大的儿子,向与其相反的方向旋转,直到那个节点被旋转到了叶节点,然后直接删除。

删除最多进行O(h)次旋转,期望复杂度是O(log n)。

 

详细的讲解还是上NOCOW  http://www.nocow.cn/index.php/Treap

 

foreverzsz原创,转载请注明出处.

本文出处:http://www.cnblogs.com/foreverzsz/archive/2010/11/11/1875021.html

相关阅读 更多 +
排行榜 更多 +
坦克冒险大师安卓版

坦克冒险大师安卓版

策略塔防 下载
自动防御

自动防御

策略塔防 下载
枪战大乱斗2

枪战大乱斗2

飞行射击 下载