• My集合框架第六弹 左式堆


    左式堆(Leftist Heaps)又称作最左堆、左倾堆。左式堆作为堆的一种,保留了堆的一些属性。

    第1,左式堆仍然以二叉树的形式构建;

    第2,左式堆的任意结点的值比其子树任意结点值均小(最小堆的特性)。但和一般的二叉堆不同,左式堆不再是一棵完全二叉树(Complete tree),而且是一棵极不平衡的树。

    package com.wpr.collection;
    
    /**
     * 左式堆:二叉堆缺点,首先,只能查找最小元素;其次,将两个堆合并的操作很麻烦
     * 		注意:所有支持有效合并的高级数据结构都需要使用链式数据结构
     * 		
     * 		定义:零路径长(null path length)npl表示从节点X到一个不具有两个儿子的节点的最短路径的长
     * 
     * @author wpr
     *
     */
    public class LeftHeap<AnyType extends Comparable<? super AnyType>> {
    
    	private Node<AnyType> root;
    	
    	public LeftHeap() {
    		root = null;
    	}
    	private static class Node<AnyType> {
    		AnyType element;
    		Node<AnyType> left;
    		Node<AnyType> right;
    		int npl;
    		public Node(AnyType element) {
    			this(element,null,null);
    		}
    		public Node(AnyType element, Node<AnyType> left, Node<AnyType> right) {
    			this.element = element;
    			this.left = left;
    			this.right = right;
    			this.npl =0 ;
    		}
    	}
    	/**
    	 * @param x
    	 */
    	public void merge(LeftHeap<AnyType> x){
    		if(this == x)
    			return ;
    		
    		root = merge(root,x.root);
    	}
    	/**
    	 * 插入一个新元素
    	 * @param x
    	 */
    	public void insert(AnyType x){
    		root = merge(new Node<AnyType>(x),root);
    	}
    	/**
    	 * 删除最小元素
    	 * @return
    	 */
    	public AnyType deleteMin(){
    		if(root == null)
    			return null;
    		
    		AnyType item = root.element;
    		root = merge(root.left,root.right);
    		
    		return item;
    	}
    	/**
    	 * 将h1和h2两个堆合并,返回根节点(递归的方式实现)
    	 * @param h1
    	 * @param h2
    	 * @return
    	 */
    	private Node<AnyType> merge(Node<AnyType> h1, Node<AnyType> h2) {
    		if(h1 == null)
    			return h2;
    		if(h2 == null)
    			return h1;
    		if(h1.element.compareTo(h2.element)<0){
    			//h1<h2
    			return merge1(h1,h2);
    		}else{
    			return merge1(h2,h1);
    		}
    	}
    	/**
    	 * 将较小的堆min和较大的堆max合并,返回根节点
    	 * @param min 较小的堆,不为null
    	 * @param max 较大的堆,不为null
    	 * @return
    	 */
    	private Node<AnyType> merge1(Node<AnyType> min, Node<AnyType> max) {
    		if(min.left==null)        //min是一个叶子节点
    			min.left = max;
    		else{
    			min.right = merge(min.right,max);	//较小堆的右子堆和较大堆合并
    			if(min.left.npl<min.right.npl){
    				swapChildren(min);
    			} 
    			min.npl = min.right.npl+1;
    		}
    		return min;
    	}
    	/**
    	 * 交换节点的左右子堆
    	 * @param min
    	 */
    	private void swapChildren(Node<AnyType> min) {
    		Node temp = min.left;
    		min.left = min.right;
    		min.right = temp;
    	}
    	/**
    	 * 非递归的方式来写一下
    	 * @param min
    	 * @param max
    	 * @return
    	 */
    /*	private Node<AnyType> merge2(Node<AnyType> h1, Node<AnyType> h2) {
    		while(h1!=null && h2!=null){
    			
    		}
    	}*/
    	public static void main(String[] args) {
    		LeftHeap<Integer> heap = new LeftHeap<>();
    		for(int i=0;i<10;i++)
    			heap.insert(i);
    		print(heap);
    	}
    	
    	public static void print(LeftHeap h){
    		while(h.root!=null){
    			System.out.println(h.deleteMin());
    		}
    	}
    }
    
  • 相关阅读:
    Snapshot--使用脚本创建快照
    Mirror--日志流压缩
    Mirror--如何TSQL查看镜像状态和镜像相关存储过程
    Mirror--如何对运行中的镜像端点更换证书
    Mirror--程序访问镜像数据库的超时机制
    oozie客户端常用操作命令
    oracle数据库表空间的创建与使用
    Idea创建sbt项目
    Idea配置sbt(window环境)
    使用Idea从github上获取项目
  • 原文地址:https://www.cnblogs.com/kakaxisir/p/4332965.html
Copyright © 2020-2023  润新知