优先队列之左式堆(JAVA实现)

来源:互联网 发布:部落实验室升级数据 编辑:程序博客网 时间:2024/06/02 03:21

一、定义:

1.零路径长度:某节点的零路径长度为该节点到没有两个儿子的节点最短距离。

2.左式堆性质:

  • 父节点属性值小于子节点属性值;
  • 堆中的任何节点,其左儿子的零路径长>=右儿子的零路径长的二叉树。
  • 任一结点的零路径长比他的诸儿子结点的零路径长的最小值多1。

二、实现思路:

1.合并:
左式堆的合并操作基于递归实现,算法思路如下:

  1. 若有一棵树是空树,则返回另一棵树;否则将根节点较大的堆与根节点较小的堆的右子树合并。
  2. 使形成的新堆作为较小堆的右子树。
  3. 如果违反了左式堆的特性,交换两个子树的位置。
  4. 更新npl(零路径长度)。

2.插入
将需要插入的节点当做一棵左式堆树,进行合并。

3.删除最小值
删除根节点,将形成的两个堆合并

三、代码实现

public class LeftistHeap<T extends Comparable> {    /**     * Created by Administrator on 2017/6/13.     */    class Node<T> {        T element;        Node<T> left;//左儿子        Node<T> right;//右儿子        int npl;//零路径长        Node(T element) {            this(element, null, null);        }        Node(T element, Node<T> left, Node<T> right) {            this.element = element;            this.left = left;            this.right = right;            npl = 0;        }    }    private Node<T> root;    /**     * 构造方法     */    public LeftistHeap() {        root = null;    }    /**     * 合并堆     *     * @param rhs 另一个左式堆     */    public void merge(LeftistHeap<T> rhs) {        if (this == rhs) {            return;        }        root = merge(root, rhs.root);        rhs.root = null;    }    public void insert(T x) {        root = merge(root, new Node(x));    }    /**     * 找出最小元素     *     * @return     */    public T findmin() {        if(isEmpty()){            System.out.println("该左式堆为空");        }        return root.element;    }    /**     * 删除最小元素     *     * @return     */    public T deleteMin() {        if (isEmpty()) {            System.out.println("该左式堆为空");        }        T minElement = root.element;        root=merge(root.left, root.right);        return minElement;    }    /**     * 是否为空     *     * @return     */    public boolean isEmpty() {        return root == null;    }    /**     * 置空     */    public void makeEmpty() {        this.root = null;    }    /**     * 合并两个左式堆(判断过程,真正合并过程由merge1操作)     *     * @param h1     * @param h2     * @return     */    private Node<T> merge(Node<T> h1, Node<T> h2) {        if (h1 == null)            return h2;        if (h2 == null)            return h1;        if (h1.element.compareTo(h2.element) > 0)            return merge1(h2, h1);        else            return merge1(h1, h2);    }    /**     * 合并两个左式堆的真正操作  h1的元素小于h2(即h2与h1的右子堆合并)     *     * @param h1     * @param h2     * @return     */    private Node<T> merge1(Node<T> h1, Node<T> h2) {        if (h1.left == null) {//h1为单节点            h1.left = h2;        } else {//h1不是单节点            h1.right = merge(h1.right, h2);            if (h1.right.npl > h1.left.npl) {//比较零路径长,确保左式堆性质不被破坏                swapChildren(h1);            }            h1.npl = h1.right.npl + 1;//零路径长为右儿子的零路径长+1        }        return h1;    }    /**     * 交换左右儿子     *     * @param t     * @return     */    private void swapChildren(Node<T> t) {        Node<T> temp = t.right;        t.right = t.left;        t.left = temp;    }    private void print(Node t){        if(t==null)            return;        print(t.left);        System.out.println(t.element+":"+t.npl);        print(t.right);    }    public static void main(String[] args) {        int numItems = 100;        LeftistHeap<Integer> h  = new LeftistHeap<>( );        LeftistHeap<Integer> h1 = new LeftistHeap<>( );        int i = 37;        for( i = 37; i != 0; i = ( i + 37 ) % numItems )            if( i % 2 == 0 )                h1.insert( i );            else                h.insert( i );        h.merge( h1 );        for( i = 1; i < numItems; i++ )            if( h.deleteMin( ) != i )                System.out.println( "Oops! " + i );    }}
原创粉丝点击