Treap树的基本操作
来源:互联网 发布:大学生单片机自学视频 编辑:程序博客网 时间:2024/05/21 10:59
3. Treap的操作
同其他树形结构一样,treap的基本操作有:查找,插入,删除等。
3.1 查找
同其他二叉树一样,treap的查找过程就是二分查找的过程,复杂度为O(lg n)。
3.2 插入
在Treap 中插入元素,与在BST 中插入方法相似。首先找到合适的插入位置,然后建立新的节点,存储元素。但是要注意新的节点会有一个优先级属性,该值可能会破坏堆序,因此我们要根据需要进行恰当的旋转。具体方法如下:
1. 从根节点开始插入;
2. 如果要插入的值小于等于当前节点的值,在当前节点的左子树中插入,插入后如果左子节点的优先级小于当前节点的优先级,对当前节点进行右旋;
3. 如果要插入的值大于当前节点的值,在当前节点的右子树中插入,插入后如果右子节点的优先级小于当前节点的优先级,对当前节点进行左旋;
4. 如果当前节点为空节点,在此建立新的节点,该节点的值为要插入的值,左右子树为空,插入成功。
Treap_Node *root;
void
Treap_Insert(Treap_Node *&P,
int
value)
//节点指针一定要传递引用 p为要插入树的根节点
{
if
(!P)
//
1
当P为空时
{
P=
new
Treap_Node;
P->value=value;
P->fix=
rand
();
//生成随机的修正值 fix为节点的优先值
}
else
if
(value <= P->value)
{
Treap_Insert(P->left,r);
if
(P->left->fix < P->fix)
Treap_Right_Rotate(P);
//左子节点优先级值小于当前节点优先级值,右旋当前节点
}
else
{
Treap_Insert(P->right,r);
if
(P->right->fix < P->fix)
Treap_Left_Rotate(P);
//右子节点修正值小于当前节点修正值,左旋当前节点
}
}
3.3:删除
跟普通的二叉查找树一样,删除结点存在三种情况。
①:叶子结点
跟普通查找树一样,直接释放本节点即可。
②:单孩子结点
跟普通查找树一样操作。
③:满孩子结点
其实在treap中删除满孩子结点有两种方式。
第一种:跟普通的二叉查找树一样,找到“右子树”的最左结点(15),拷贝元素的值,但不拷贝元素的优先级,然后在右子树中
删除“结点15”即可,最终效果如下图。
第二种:将”结点下旋“,直到该节点不是”满孩子的情况“,该赋null的赋null,该将孩子结点顶上的就顶上,如下图:
当然从理论上来说,第二种删除方法更合理,这里我写的就是第二种情况的代码。
1 #region 删除当前树中的节点 2 /// <summary> 3 /// 删除当前树中的节点 4 /// </summary> 5 /// <param name="key"></param> 6 /// <returns></returns> 7 public void Remove(K key, V value) 8 { 9 node = Remove(key, value, node);10 }11 #endregion12 13 #region 删除当前树中的节点14 /// <summary>15 /// 删除当前树中的节点16 /// </summary>17 /// <param name="key"></param>18 /// <param name="tree"></param>19 /// <returns></returns>20 public TreapNode<K, V> Remove(K key, V value, TreapNode<K, V> tree)21 {22 if (tree == null)23 return null;24 25 //左子树26 if (key.CompareTo(tree.key) < 0)27 {28 tree.left = Remove(key, value, tree.left);29 }30 //右子树31 if (key.CompareTo(tree.key) > 0)32 {33 tree.right = Remove(key, value, tree.right);34 }35 /*相等的情况*/36 if (key.CompareTo(tree.key) == 0)37 {38 //判断里面的HashSet是否有多值39 if (tree.attach.Count > 1)40 {41 //实现惰性删除42 tree.attach.Remove(value);43 }44 else45 {46 //有两个孩子的情况47 if (tree.left != null && tree.right != null)48 {49 //如果左孩子的优先级低就需要“左旋”50 if (tree.left.priority < tree.right.priority)51 {52 tree = RotateLL(tree);53 }54 else55 {56 //否则“右旋”57 tree = RotateRR(tree);58 }59 60 //继续旋转61 tree = Remove(key, value, tree);62 }63 else64 {65 //如果旋转后已经变成了叶子节点则直接删除66 if (tree == null)67 return null;68 69 //最后就是单支树70 tree = tree.left == null ? tree.right : tree.left;71 }72 }73 }74 75 return tree;76 }77 #endregion
- Treap树的基本操作
- BZOJ3224 [Tyvj 1728] [普通平衡树] Treap的基本操作
- Treap 基本操作
- Treap树堆的基本模板(无讲解)
- 【线段树,Treap】BZOJ2770 YY的Treap
- treap树的操作--查找区间第k大
- Treap堆的插入,删除操作
- 【BZOJ2333】【SCOI2011】棘手的操作 treap合并
- [线段树 Treap] BZOJ 2770 YY的Treap
- Treap学习基本入门
- Treap 基本ADT
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- 树的基本操作
- linux 文件操作 --copy_file
- Mysql replace 与 insert on duplicate效率分析
- 虚函数运行机制
- HDU 2577(How to Type)动态规划
- 本人常用资源整理(ing...)
- Treap树的基本操作
- [数论]唯一分解定理
- UITableViewCell的背景颜色设置
- java中的监听器(listener)
- vector的clear操作的内部过程
- Android Studio调试技巧
- Python tools for Visual Studio 插件
- AFNetworking 取消请求
- [leetcode-103]Binary Tree Zigzag Level Order Traversal(java)