【伸展树】自顶向下写法
来源:互联网 发布:淘宝怎么找人工客服 编辑:程序博客网 时间:2024/06/06 01:38
一般的伸展树都是自底向上的吧...因为大部分人都是足控喜欢简单的实现。
参考了很多网上的写法,自顶向下写法中有两点比较容易令人看不懂,这里特意解释一下。
splay的思路是把原树劈成3棵树,左树小于目标节点的值,右树大于目标节点的值,中树是未知的。
图片引用自这里
tree_node * splay(int i, tree_node * t){ tree_node N, *l, *r, *y; if(t == NULL) return t; N.left = N.right = NULL;</span> l = r = &N; for(;;) { if(i < t->item) { if(t->left == NULL) break; if(i < t->left->item) { y = t->left; t->left = y->right; y->right = t; t = y; if(t->left == NULL) break; } r->left = t; r = t; t = t->left;</span> } else if(i > t->item) { if(t->right == NULL) break; if(i > t->right->item) { y = t->right; t->right = y->left; y->left = t; t = y; if(t->right == NULL) break; } l->right = t; l = t; t = t->right;</span> } else { break; } } l->right = t->left; r->left = t->right; t->left = N.right; t->right = N.left; return t;}
程序引用自这里
要点1:图中使用了L和R两棵树,而程序实现时为了方便操作,使用了一个中间节点N,它的左右子树就是LR,相当于把LR挂在了N上,然后LR向下互不干扰的拓展。
要点2:中树向下拓展中需要把多余的节点转移到LR树上去,这时我们可以发现,如果转移向L,那么应该连向它的最右节点(根据值的关系后转移到左树上的节点更大一些,所以需要接到左树的最大值上),R则反之。所以我们需要一个操作去查找LR树的最大,小值节点(这个谁都会),但是程序里没有出现相关的代码片段,所以这里有蹊跷猫腻姿势黑科技技巧。奥秘在于每次转移向LR的子树都不存在右或左子树(具体自己体会吧...),所以我们连接完成后直接令LR向右或左前进一步,暴露出它的空子树,方便我们直接连接,同时也完成了我们寻找最大,小位置插入的过程。
最后填上我缩短的代码:
#include <cstdio>struct node{int v; node *ch[2];}Nodes[500000]; int tail = 1;node *newNode(int v){node *n = Nodes + tail++;n->v = v; n->ch[0] = n->ch[1] = NULL;return n;}void rotate(node *&x, int d){node *y = x->ch[d]; x->ch[d] = y->ch[d^1]; y->ch[d^1] = x; x = y;}node *splay(node *x, int v){node N; node *T[2] = {&N, &N};while(x->v != v){int d = (x->v > v ? 0 : 1);if(x->ch[d] && (d ? x->ch[d]->v < v : x->ch[d]->v > v)){rotate(x, d);}if(!x->ch[d]) break;T[d^1]->ch[d] = x; T[d^1] = x; x = x->ch[d];}T[0]->ch[1] = x->ch[0]; T[1]->ch[0] = x->ch[1];x->ch[0] = N.ch[1]; x->ch[1] = N.ch[0];return x;}node *insert(node *x, int v){if(!x){x = newNode(v); return x;}else {x = splay(x, v);if(x->v == v) return x;else{int d = (x->v > v ? 0 : 1);node *t = newNode(v);t->ch[d] = x->ch[d]; x->ch[d] = NULL; t->ch[d^1] = x;return t;}}}node *erase(node *x, int v){if(!x) return NULL;x = splay(x, v);if(x->v == v){int d = (x->ch[0] ? x->ch[1] ? -1 : 1 : 0);if(d == -1){d = v & 1; node *t =splay(x->ch[d], v); t->ch[d^1] = x->ch[d^1];return t;}else return x->ch[d^1];}return x;}void travel(node *x){if(x){travel(x->ch[0]);printf("%d ", x->v);travel(x->ch[1]);}}int main(){node *root = NULL;for(int x; ~scanf("%d", &x) && x != 0; root = insert(root, x), travel(root), printf("\n"));for(int x; ~scanf("%d", &x) && x != 0; root = erase(root, x), travel(root), printf("\n"));return 0;}
0 0
- 【伸展树】自顶向下写法
- 自顶向下伸展树
- 伸展树——自顶向下
- C++伸展树自顶向下实现
- 《DSAA》 12.1 自顶向下伸展树
- 伸展树 自底向上 自顶向下
- 自顶向下伸展树头文件C语言
- 自顶向下伸展树实现文件C语言
- 伸展树(splay tree)自顶向下的算法
- 高级数据结构实现——自顶向下伸展树
- 伸展树介绍 - 使用自顶向下的调整算法
- 伸展树---(自顶向下的设计)
- 《数据结构与算法分析》伸展树(自顶向下)详解
- 自顶向下,精益求精
- 自顶向下
- 自顶向下设计
- 自顶而下伸展树 数据结构说解
- 计算机网络自顶向下方法
- POJ 1679 The Unique MST
- Android组件:Intent与Activity生命周期实例详解
- 输入输出流的转换
- Path Sum(LeetCode)
- poj3565最小匹配
- 【伸展树】自顶向下写法
- (c语法百题7)求两数的整数商 和 余数
- ArcGIS Geadatabase地理数据库的类型
- 选择排序原理及实现
- Bufferedimage 简单图片操作
- codeforces 453 B Little Pony and Harmony Chest (状压dp)
- [leetcode] Rotate List
- 让你提前认识软件开发(43):软件产品升级流程
- 【开源项目】Smart,让魅族Smartbar变得Smart,Version:2.0