社区讨论
FHQ-Treap 分裂递归瓶颈,关于递归回溯
P3369【模板】普通平衡树参与者 3已保存回复 8
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @mdkdw45p
- 此快照首次捕获于
- 2025/07/26 23:07 7 个月前
- 此快照最后确认于
- 2025/11/04 03:40 4 个月前
想写详解,然后自己遇到瓶颈了(捂脸
大概是这样:
分裂模板:
C/*
split 函数:按值分裂树
now:当前处理的节点下标
val:分裂的关键值
x:输出参数,存储所有值<=val的子树根
y:输出参数,存储所有值>val的子树根
递归地将树分裂为两部分:
x:所有值<=val的子树的根节点
y:所有值>val的子树的根节点
*/
void split(int now,int val,int &x,int &y)//直接修改外面的全局变量 x 和 y
{
if(!now)
{
x=y=0;
return;
}
if(tree[now].val<=val)//当前节点值<=val,应放入x树
{
x=now;// 当前节点作为x树的根
split(tree[now].r,val,tree[now].r, y);//递归处理右子树,分裂点仍然是val
}
else//当前节点值>val,应放入y树
{
y=now;//当前节点作为y树的根
split(tree[now].l,val,x,tree[now].l);//递归处理左子树,分裂点仍然是val
}
}
问题是这样的:
我现在有一棵树(圈内为权值,圈外为编号):
我们假设给定的 ,为了让大家更直观体验递归过程,我挑战手算递归!
| 递归次数 | now | val | x | y | 递归操作 |
|---|---|---|---|---|---|
| 第一次处理 | 1 | 6 | 0 | 1 | split(tree[1].l=2,3,x=0,tree[1].l=2) |
| 第二次处理 | 2 | 2 | 2 | 2 | split(tree[2].r=4,3,tree[2].r=4, y=2) |
| 第三次处理 | 5 | 4 | 4 | 5=tree[1].l | split(tree[5].l=0,3,x=2,y=tree[5].l=0) |
| 第四次处理 | 0,return后回溯 | 无 | 0 | 0 | return |
第一次回溯(回到split(tree[2].r=4,3,tree[2].r=5, y)) | 5 | 4 | 0 | 5 | return |
第二次回溯(回到split(tree[1].l=2,3,x=0,tree[1].l)) | 2 | 2 | 2 | tree[2].y=y=4 | return |
第三次回溯(回到split(root=3,3,x,y)) | 1 | 6 | tree[1].l=x=2 | 6 | 结束 |
但是回溯这边我自己都没看懂,需要更详细的说明,哪位大佬可以帮助我(就当我递归底子没打好)?
回复
共 8 条回复,欢迎继续交流。
正在加载回复...
