左式堆的合并

package heap;

import java.util.Stack;

public class LeftHeap
{
    int num ;
    LeftHeap left ;
    LeftHeap right ;
    int npl ;

    public LeftHeap() {}

    public LeftHeap(int num, int npl) {
        this.npl = npl;
        this.num = num;
    }

    /**
     * 左式堆合并的非递归实现
     */
    public static LeftHeap merge_unrec(LeftHeap h1 , LeftHeap h2)
    {
        if(h1 == null || h2 == null)
            return h1 == null ? h2 : h1 ;

        Stack<LeftHeap> stack = new Stack<>() ; //用于保存每一级的父节点

        while (h2 != null || !stack.isEmpty())
        {
            if(h1 != null && h2 != null)
            {
                if(h1.num > h2.num) //确保h1为小值的堆,h2为大值的堆
                {
                    LeftHeap temp = h1 ;
                    h1 = h2 ;
                    h2 = temp ;
                }

                if(h1.left == null) //当小堆的左子树为空时, 直接将h2作为他的左子树即可, 由于仍不存在右子树, 所以npl无需更新
                {
                    h1.left = h2 ;
                    h2 = null ;
                }
                else
                {
                    stack.push(h1) ;    //说明左右子树都存在, 此时应将h1保存, 让h1的右子树和h2进行合并
                    h1 = h1.right ;
                }
            }
            else  //各级的父节点连接右子树
            {
                if(h1 == null)
                {
                    h1 = h2 ;
                    h2 = null ;
                }
                while (!stack.isEmpty())
                {
                    LeftHeap heap = stack.pop() ;
                    heap.right = h1 ;
                    if(heap.left.npl < heap.right.npl)
                        swapLR(heap) ;
                    heap.npl = heap.right.npl+1 ;
                    h1 = heap ;
                }
            }
        }
        return h1 ;
    }

    public static LeftHeap merge(LeftHeap h1 , LeftHeap h2)
    {
        if(h1 == null || h2 == null)
            return h1 == null ? h2 : h1 ;
        if(h1.num > h2.num)
            return merge1(h2 , h1) ;
        else
            return merge1(h1 , h2) ;
    }

    private static LeftHeap merge1(LeftHeap h1 , LeftHeap h2)
    {
        if(h1.left == null)
            h1.left = h2 ;
        else
        {
            h1.right = merge(h1.right , h2) ;
            if(h1.left.npl < h1.right.npl)
                swapLR(h1) ;
            h1.npl = h1.right.npl+1 ;
        }

        return h1 ;
    }

    private static void swapLR(LeftHeap h)
    {
        LeftHeap temp = h.left ;
        h.left = h.right ;
        h.right = temp ;
    }

    public static void inOrder(LeftHeap heap)
    {
        if(heap == null)
            return ;
        inOrder(heap.left);
        System.out.print(heap.num + " ");
        inOrder(heap.right);
    }
    public static void main(String[] args)
    {
        LeftHeap h1 = new LeftHeap(3, 1) ;
        LeftHeap h2 = new LeftHeap(10, 1) ;
        LeftHeap h3 = new LeftHeap(8, 0) ;
        LeftHeap h4 = new LeftHeap(21, 0) ;
        LeftHeap h5 = new LeftHeap(14, 0) ;
        LeftHeap h6 = new LeftHeap(17, 0) ;
        LeftHeap h7 = new LeftHeap(23, 0) ;
        LeftHeap h8 = new LeftHeap(26, 0) ;

        h1.left = h2 ;
        h1.right = h3 ;
        h2.left = h4 ;
        h2.right = h5 ;
        h3.left = h6 ;
        h5.left = h7 ;
        h6.left = h8 ;

        LeftHeap a = h1 ;

        h1 = new LeftHeap(6,2) ;
        h2 = new LeftHeap(12,1) ;
        h3 = new LeftHeap(7,1) ;
        h4 = new LeftHeap(18,0) ;
        h5 = new LeftHeap(24,0) ;
        h6 = new LeftHeap(37,0) ;
        h7 = new LeftHeap(18,0) ;
        h8 = new LeftHeap(33,0) ;

        h1.left = h2 ;
        h1.right = h3 ;
        h2.left = h4 ;
        h2.right = h5 ;
        h3.left = h6 ;
        h3.right = h7 ;
        h5.left = h8 ;

        LeftHeap b = h1 ;

        LeftHeap heap = merge_unrec(a , b) ;

        inOrder(heap) ;

    }
}

左式堆合并的时间复杂度为O(N) , 由于n个节点的左式堆的右子树最多含有log(N+1)个节点, 而且每次合并都是与较小值堆的右子树进行比较, 所以为O(N)

时间: 2024-10-14 03:11:06

左式堆的合并的相关文章

第十章&#160;优先级队列 (xa2)左式堆:合并

原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/10280552.html

左式堆的实现与详解

定义:左式堆(Leftist Heaps)又称作最左堆.左倾堆,是计算机语言中较为常用的一个数据结构.左式堆作为堆的一种,保留了堆的一些属性.第1,左式堆仍然以二叉树的形式构建:第2,左式堆的任意结点的值比其子树任意结点值均小(最小堆的特性).但和一般的二叉堆不同,左式堆不再是一棵完全二叉树(Complete tree),而且是一棵极不平衡的树. 性质: 零路径长:从X到一个不具有两个儿子的结点的最短路径的长. 1. 任一结点的零路径长比他的诸儿子结点的零路径长的最小值多1 2. 父节点属性值小

左式堆

零路径长:从X到一个不具有两个儿子的结点的最短路径的长. 性质: 任一结点的零路径长比他的诸儿子结点的零路径长的最小值多1 父节点属性值小于子节点属性值: 堆中的任何节点,其左儿子的零路径长>=右儿子的零路径长:的二叉树. 下面是左式堆的类型声明: 1 template <typename Comparable> 2 class LeftistHeap 3 { 4 public: 5 LeftistHeap(); 6 LeftistHeap(const LeftistHeap &

数据结构--左式堆的思想和代码

左式堆也是实现优先列队的一种数据结构,和二叉堆一样,左式堆也具有堆序性和结构性. 堆序性: 一个节点的后裔都大于等于这个节点. 结构性:左式堆也是二叉树,和二叉堆的唯一区别在于左式堆不是理想平衡的,实际上是趋于非常不平衡,对于堆中每一个节点X,左儿子的零路径长至少与右儿子的零路径长一样大,零路径长Npl的定义为:节点到一个没有两个儿子的节点的最短路径长,因此具有0个或者1个儿子节点的Npl为0,Npl(NULL) = -1. 左式堆可以高效的支持合并操作,而插入和删除操作都可以通过合并操作来实现

堆之左式堆和斜堆

d-堆 类似于二叉堆,但是它有d个儿子,此时,d-堆比二叉堆要浅很多,因此插入操作更快了,但是相对的删除操作更耗时.因为,需要在d个儿子中找到最大的,但是很多算法中插入操作要远多于删除操作,因此,这种加速是现实的. 除了不能执行find去查找一般的元素外,两个堆的合并也很困难. 左式堆 左式堆可以有效的解决上面说的堆合并的问题.合并就涉及插入删除,很显然使用数组不合适,因此,左式堆使用指针来实现.左式堆和二叉堆的区别:左式堆是不平衡的.它两个重要属性:键值和零距离 零距离(英文名NPL,即Nul

转载:数据结构 左式堆

简介 设计一种堆结构像二叉堆那样高效的支持合并操作而且只使用一个数组似乎很困难.原因在于,合并似乎需要把一个数组拷贝到另一个数组中去,对于相同大小的堆,这将花费O(N).正因为如此,所有支持高效合并的高级数据结构都需要使用指针. 像二叉堆那样,左式堆也有结构性和堆序性.不仅如此,左式堆也是二叉树,它和二叉堆之间的唯一区别在于:左式堆不是理想平衡的,而实际上是趋向于非常不平衡. 左式堆性质 把任意节点X的零路径长(null path length, NPL)Npl(X)定义为从X到一个没有两个儿子

结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆

实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等. 1. 二叉堆 1.1. 定义 完全二叉树,根最小. 存储时使用层序. 1.2. 操作 (1). insert(上滤) 插入末尾 26,不断向上比较,大于26则交换位置,小于则停止. (2). deleteMin(下滤) 提取末尾元素,放在堆顶,不断下滤: (3). 其他操作: 都是基于insert(上滤)与deleteMin(下滤)的操作. 减小元素:减小节点的值,上滤调整堆. 增大

Heap:左式堆的应用例(任意序列变单调性最小价值)

首先来说一下什么是左式堆: A:左式堆是专门用来解优先队列合并的麻烦(任意二叉堆的合并都必须重新合并,O(N)的时间). 左式堆的性质: 1.定义零路经长:节点从没有两个两个儿子节点的路经长,把NULL定义为-1 2.堆性性质(x的键值比x左右两个儿子节点的键值要大或者要小) 3.堆中的每一个节点x,左儿子的零路经长至少与右儿子的零路经长一样长. 4.节点的距离等于右节点的距离+1. 引理: 若左式堆的距离定义为一定值,则节点数最少的左式堆是完全二叉堆. 定理: 若左式堆的距离为k,则这棵树最少

My集合框架第六弹 左式堆

左式堆(Leftist Heaps)又称作最左堆.左倾堆.左式堆作为堆的一种,保留了堆的一些属性. 第1,左式堆仍然以二叉树的形式构建: 第2,左式堆的任意结点的值比其子树任意结点值均小(最小堆的特性).但和一般的二叉堆不同,左式堆不再是一棵完全二叉树(Complete tree),而且是一棵极不平衡的树. package com.wpr.collection; /** * 左式堆:二叉堆缺点,首先,只能查找最小元素:其次,将两个堆合并的操作很麻烦 * 注意:所有支持有效合并的高级数据结构都需要