zoukankan      html  css  js  c++  java
  • 从零开始“发明”Treap

    首先考虑我们要解决的问题:让一个不断插入新元素的BST保持平衡,即深度控制在$log n$级别。

    众所周知,一个随机顺序插入的BST是平衡的(容易发现随机插入构建的树深度等价于进行一次随机快速排序的最大递归层数,既选一个根最先插入,然后递归下去),所以我们想做的大概就是让每次插入后,树的结构和随机插入构成的树一样。

    当然,一种巧妙(或者更加自然)的方法是每插入$sqrt{n}$个元素后线性重构整颗树做到根号复杂度,或者根据树的结构随时重构(也就是“替罪羊树”,可以做到$n log n$的复杂度),在这里先不讨论。

    所以,最直接的想法就是给每个点一个随机权值作为他的相对插入顺序,这样所有新加入的节点也相当于是“随机插入”的。而不难发现要让树的结构满足条件,我们只需要在满足BST结构的同时让随机权值满足堆的性质,也就是父亲节点一定比子结点先插入。这样,我们就自然的“发明”了Treap。接下来只需要找到一种操作使我们能在不破坏BST性质的同时实现堆的“上移”操作,而这就是zig-zag旋转操作。这个操作是$O(1)$的,所以维护这颗树的复杂度和维护一个堆是一样的。

    事实上,我们考虑构造BST的另一种表述:给定一颗二叉树的中序遍历, 构造一颗对应的二叉树使得其深度尽量小。我们知道,对于一颗二叉树,只需要确定它的中序遍历与后序遍历就可以唯一确定这棵树。具体过程就是后序遍历的最后一个点一定是树根,我们找到根在中序遍历里的位置以后就可以把中序遍历中两侧的点分治处理。也就是说,最终获得的树结构满足父亲在后序遍历中的位置大于儿子,既每个点在后序遍历中出现的位置在原树中满足堆的性质。

    所以,我们随机“插入顺序”其实就是随机这棵树的后序遍历。

  • 相关阅读:
    通过圆形按钮的绘制熟悉Qt的绘图机制,掌握这种终极方法
    Qt用委托绘制需要的图形的步骤
    定位问题的一个思路
    头文件找不到引用的类的定义
    model的index无限次数执行导致stackOverFlow
    error C2248: 'QObject::QObject' : cannot access private member declared in class 'QObject'
    Python爬虫之使用celery加速爬虫
    Python之celery的简介与使用
    NLP入门(七)中文预处理之繁简体转换及获取拼音
    NLP入门(六)pyltp的介绍与使用
  • 原文地址:https://www.cnblogs.com/Cubelia/p/13471425.html
Copyright © 2011-2022 走看看