• 左偏树


    摘要:
    左偏树是一种优先队列,虽然有些简陋,但它可以比较高效的实现队列的合并操作,所以在一些涉及到最值,以及合并的问题中,不妨考虑下这种数据结构。

    [可并堆与左偏树]

    我们最常用的二叉堆,是最常用的优先队列,它可以在O(logN)内实现插入和删除最小值操作。但是对于合并两个有序的优先队列,二叉堆就显得力不从心了。

    左偏树是一种可并堆(Mergeable Heap),意思是可以在O(logN)时间内完成两个堆的合并操作。左偏树(Leftist Tree),或者叫左倾树,左式树,左式堆(Leftist Heap),左堆。顾名思义,它好象是向左偏的,实际上它是一种趋于非常不平衡的二叉树结构,但却能够实现对数级的合并时间复杂度。

    [左偏树的定义]

    左偏树是一棵二叉树,每个节点具有四个属性:左子树(left),右子树(right),键值(key),零路径长(npl)。其中节点i的零路径长的定义为从i到i子树中最近的没有两非空个子节点的节点的路径的长度。空节点的零路径长为为-1,只有一个非空子节点的节点的零路径长为0。左偏树的节点之间除了满足堆序以外,还应满足节点左子节点的零路径长不小于右子节点的零路径长。

    根据上述定义,很容易得出:对于非空节点i,满足i.npl=i.right.npl+1。还有一个性质,一棵节点数为N的左偏树,根节点的零路径长最大为⎣log(N+1)⎦-1,即O(logN),证明略。

    [左偏树的合并]

    左偏树的一切操作都是在合并的基础上进行的,所以要先讨论合并。

    当合并两个左偏树节点a,b时,要求是这两个节点是没有包含关系的。假设a.key

    [左偏树的插入和删除]

    对已有的左偏树a插入新的值p,只需把p构建为一个只有一个元素左偏树节点b,然后合并a,b即可。

    删除左偏树的最小节点,只需把根节点删除,然后合并两个子树,作为新的根节点。

    [左偏树的构建]

    可以用一个队列,使左偏树的构建为O(N)。具体方法为

    把所有元素作为一个单独左偏树节点放入队列;
    不断取出两个队首的左偏树,合并这两个左偏树,然后放入队尾;
    当队列中只剩下一个左偏树,算法结束。可以证明,时间复杂度为O(N)。

    [对左偏树的比较]

    左偏树可以实现二叉堆的一切功能,而且还能实现二叉堆不易实现的合并,个人认为实际编程中左偏树更有理性,不容易错。但左偏树的算法时间常数要大于二叉堆,所以不能完全代替之。

    和平衡树相比,左偏树采取了与平衡树完全相反的构造策略。平衡树为了实现所有元素的快速查找,使节点尽量趋于平衡。而左偏树的目的是实现快速的查询最小值与合并操作,恰恰要让节点尽量向左偏。最优的平衡树,恰恰是最差的左偏树,而最优的左偏树,恰恰是平衡树退化的结果。

    斜堆、二项堆、斐波那契堆也是可并堆实现的有效方法,而且二项堆、斐波那契堆实际中会比左偏树更快,但是在时间与编程复杂度的性价比上,左偏树有着绝对的优势。

    参考博客

    https://www.byvoid.com/zhs/blog/leftist-tree
    http://www.cnblogs.com/yc_sunniwell/archive/2010/06/28/1766756.html

    题集

    https://vjudge.net/contest/226630#overview

  • 相关阅读:
    Golang调用windows下的dll动态库中的函数
    Golang 编译成 DLL 文件
    go 通过nginx代理后获取用户ip
    idea教程--Maven 骨架介绍
    idea教程--快速插入依赖
    Java开发名词解释
    Android Studio安装
    Java基础--Eclipse关联Java源码
    【排序基础】3、随机生成排序算法 测试用例
    【排序基础】2、使用模板(泛型)编写选择排序算法
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9386967.html
Copyright © 2020-2023  润新知