zoukankan      html  css  js  c++  java
  • 笛卡尔树学习笔记

    这种数据结构并不常用,但有时候对简化思维和优化复杂度有一定的帮助。

    简介

    笛卡尔树是一个二叉树,每一个节点由两个键值构成,((k,w)) 其中,(k) 满足二叉搜索树的性质,(w) 满足二叉堆的性质,

    如果给定数组 (a),以数组下标作为 (k),用数组里面存放的值作为 (w),则不难发现这个笛卡尔树的性质,一棵子树内的下标对应一段连续的区间,当然我们建立笛卡尔树不能只是对数组建立,这样具有一定的特殊性,我们要对于任意的二元组建立笛卡尔树。

    构建

    对任意二元组建立笛卡尔树的方法如下:

    • 首先,我们将所有的二元组按照 (k),也就是第一关键字来排序。

    • 我们定义 右链 为从根节点开始,如果有右儿子就一直走下去,走过的点形成的链。

      我们考虑这样 增量 来构造笛卡尔树,设当前的二元组为 ((a,b))

    • 我们从右链的最低端开始遍历,设当前遍历的二元组为 ((c,d)),如果我们有 (b<d) 那么就停止遍历,将插入点设置为当前遍历的 子树,把插入点的左子树设置为当前遍历点以前的右儿子。

    考虑正确性证明:

    • 首先关注到 (k) 是有序的,因为我们是把当前遍历点设置为插入点的 子树,所以这样显然满足二查搜索树性质,又因为我们是遍历到有 (b<d) 的时候才插入,所以很显然这棵树的第二关键字也满足堆的性质。

    考虑复杂度证明:

    • 首先显然,如果一个当前插入点遍历到了一个点却没有选择插入,那么这个点以后就不会存在在右链之中,也就是说,每个点仅会被最多 经过 一次,所以复杂度是均摊 (O(n))

    考虑实现,我们可以用栈来模拟右链,插入代码如下:

    inline void Insert(int k){
        int Last=Top;
        while(W[Stack[Last]]>h[k]) Last--;
        ls[k]=rs[Last]
        rs[Last]=k;
        Stack[++Last]=k;
        Top=k;
    }
    

    注意,以上实现仅供参考,正确性并不保证。可能会有所修改。

  • 相关阅读:
    第一篇代码 嗨翻C语言 21点扑克
    Windows7 sp1 64位下安装配置eclipse+jdk+CDT+minGW
    MinGW-64 安装
    Windows Live Writer配置步骤
    Css 居中
    c++ 常量成员函数
    c/c++ 引用计数
    C++ 《STL源码剖析》学习-vector
    C/C++ 有符号数和无符号数
    cocos2d 内存管理机制
  • 原文地址:https://www.cnblogs.com/TianMeng-hyl/p/15505201.html
Copyright © 2011-2022 走看看