动态树的具体操作

-------------------(摘自《高级数据结构》)

用splay维护实路径,
用深度作为关键字给节点排序,那么我们将得到唯一一个有序节点。
在实现操作之前,我们还需要维护一些额外信息。为了能够在这些实路径之间建立关系,使得我们能够知道这些路径在树结构中的组织方式,我们要为每一颗splay树额外维护其path-parent,即每颗splay对应的实路径中深度最小的父节点。注意实路径,splay以及维护的森林这三者之间的关系和区别。
access(v)
上述操作中除了第一个意外,其余都需要用到基础操作,access(v),
1)如果节点v不是其所在实路径头部,即v有子节点u与之用实边相连,那么需要先断开这条边,方法是首先将节点v用splay操作旋转到哦其所在平衡树的根节点,然后v肯定有右子树,故将v与v的右子树分离,同时将v的右子树的path-parent设置为v;
2)如果节点v所在的平衡树包含根节点,那么该过程结束;否则,转步骤3)
3)设u为v所在的平衡树的path-parent。将u用splay操作旋转到其根节点,并且用v所在的平衡树替换u的右子树,这样就实现了路径的向上延伸。还需要分离原来u的右子树,原来的右孩子记为w。此时w的path-parent就为u了。然后继续转步骤2)

void access(v){
splay(v);
v->rightchild->Path_Parent=v;
v->rightchild=Null;
while (v->Path_Parent!=Null){
  u=v->Path_Parent;
  splay(u);
  u->rightchild->Path_Parent=u;
  u->rightchild=v;
 v=u;
 }

return 0;
}
//这段伪代码很好理解

2.find_root(v)
有了access(v)操作,寻找树根的操作就比较简单了。我们只要对节点v执行access(v)操作,使得v与要找的根节点在同一颗平衡树中了。然后,要找的根节点一定是实路径的尾部,即平衡树中的最左节点。

void find_root(int v){
   access(v);
   splay(v);//此处还没想通为啥要splay一次。
   while(v->leftchild!=Null)
   {
     v=v->leftchild;
  }
return v;
}

3.evert(v)
该操作等价于将v到v所在的树的根节点的路径上的所有边取反。首先执行acess(v),我们便已经将该条路径取出了。由于路径是用平衡树维护的,所以需要执行的是平衡树的逆序。普通方法重构平衡树需要O(n)的时间,然而实际上我们可以借鉴线段树的延迟修改思想,给平衡树节点也打上标记进行反序。这里由于是对整颗平衡树反序,所以标记应该打在平衡树的根节点处,用打标记的方式维护的时候,要对平衡树的旋转等操作进行相应的维护。

void evert(int v)
{
  access(v);
  splay(v);
  reverse(v);
}

4.link(u,v)
为了保证连接后得到的树的形态仍然合法(即为有根树)我们首先需要令u成为其所在树的根节点。我们将u变为其所在树的根节点,同时要将u用splay操作移动到平衡树的根节点。此时,u的左子树必然为空。我们将v用splay操作移动到其所在平衡树的根节点。然后令u的左孩子为v,完成连接操作,然后令u的左孩子为v,便完成了连接操作。

void link(int u,int v){
evert(u);
access(u);
splay(u);
access(v);
splay(v);
u->leftchild=v;
}

5.cut(u,v)
执行该操作时,首先要将u置为有根树的根节点,从而保证v一定是u的子节点,再对v执行access操作,我们便将u和v合并到同一颗平衡树中了。此时对v执行splay操作使其成为所在平衡树的根节点,同时分离v和v的左子树,便完成了删边操作。

void cut(int u,int v)
{
evert(u);
access(v);
splay(v);

v->leftchild=Null;
}

Make_Tree操作和其他一些操作略去。

全部评论

相关推荐

不愿透露姓名的神秘牛友
2024-12-30 18:02
程序员牛肉:1.可以标记一下自己的学校是985,有一些hr可能没想到你这个院校是985的。 2.简历所呈现出来的能力还是有点差的,苍穹外卖+黑马点评。这在java技术域里面也就是刚学三四个月的样子,大厂现在招人少,小厂又更加希望你能直接过来干活。就你简历上呈现出来的能力,确实是有点难找,肉眼可见的不懂技术。 第一个项目中:简单的使用redis也算是亮点嘛?使用jwt,threadlocal也算是亮点?你不就是调了几个包嘛?Nginx作为服务器也能写出来,这不是前端的活嘛? 第二个项目中:分布式锁+mq消息队列+Lua队列。真没啥好问的。属于面试官看一眼就阳痿的简历,没有任何想提问的欲望。 我给你建议是好好的挖一挖这个项目吧,其实苍穹外卖和黑马点评这两个项目很不错了,只不过是太烂大街了导致面试官没啥问的兴趣,所以不太推荐写简历上。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务