二叉堆V2.0(含比较器,Java语言描述)

更新说明

我们在此前已经编写过简单版的二叉大根堆V1.0,这次,换成二叉小根堆,命名为二叉堆V2.0。

大家也知道,堆是完全二叉树,存储方式借助动态数组实现顺序存储,依赖于父子结点之间的index关系实现类似于二叉树式的访问,也支持数组本身的按编号随机访问和顺序访问。

二叉堆和二叉搜索树有很大的不同,但新学的人可能会弄混,这里有二者的辨析文。

堆是很有用的一种数据结构,二叉堆是常见形式。
堆排序、优先队列、堆的其他变形……都离不开对二叉堆的理解。
很多算法题都能涉及到堆,堆还真是个好东西!
对于新手而言,也必须掌握二叉堆建堆、插入、删除、调整的代码,能编写堆排序的代码。
堆真的很重要,一定要掌握!!!
虽说有大根堆和小根堆,但无非一个是最大值在堆顶,一个是最小值在堆顶,其实是一个东西。不信的话,你品,你细品,又有什么差别呢?
好啦,开始正题,不懂的自己去学。

核心功能

  • void insert(x) → Insert x
  • Comparable deleteMin() → Return and remove smallest item
  • Comparable findMin() → Return smallest item
  • boolean isEmpty() → Return true if empty; else false
  • void makeEmpty() → Remove all items

异常类

当集合容器为空的时候就不能够删除或获取元素,这时就会出现一种异常,命名为UnderflowException:

/**
 * Exception class for access in empty containers
 * such as stacks, queues, and priority queues.
 */
public class UnderflowException extends RuntimeException {}

编程实现

/**
 * Implements a binary heap.
 * Note that all "matching" is based on the compareTo method.
 */
public class BinaryHeap<T extends Comparable<? super T>> {

    /**
     * Construct the binary heap.
     */
    public BinaryHeap() {
        this(DEFAULT_CAPACITY);
    }

    /**
     * Construct the binary heap.
     * @param capacity the capacity of the binary heap.
     */
    @SuppressWarnings("unchecked")
    public BinaryHeap(int capacity) {
        currentSize = 0;
        array = (T[]) new Comparable[capacity+1];
    }
    
    /**
     * Construct the binary heap given an array of items.
     */
    @SuppressWarnings("unchecked")
    public BinaryHeap(T[] items) {
        currentSize = items.length;
        array = (T[]) new Comparable[(currentSize+2)*11/10];
        int i = 1;
        for(T item : items) {
            array[i++] = item;
        }
        buildHeap();
    }

    /**
     * Insert into the priority queue, maintaining heap order.
     * Duplicates are allowed.
     * @param x the item to insert.
     */
    public void insert(T x) {
        if(currentSize == array.length-1) {
            enlargeArray(array.length*2+1);
        }
        int hole = ++currentSize;
        for(array[0] = x; x.compareTo(array[hole/2]) < 0; hole/=2) {
            array[hole] = array[hole/2];
        }
        array[hole] = x;
    }

    @SuppressWarnings("unchecked")
    private void enlargeArray(int newSize) {
        T[] old = array;
        array = (T[]) new Comparable[newSize];
        for(int i = 0; i < old.length; i++) {
            array[i] = old[i];
        }
    }
    
    /**
     * Find the smallest item in the priority queue.
     * @return the smallest item, or throw an UnderflowException if empty.
     */
    public T findMin() {
        if(isEmpty()) {
            throw new UnderflowException();
        }
        return array[1];
    }

    /**
     * Remove the smallest item from the priority queue.
     * @return the smallest item, or throw an UnderflowException if empty.
     */
    public T deleteMin() {
        if(isEmpty()) {
            throw new UnderflowException();
        }
        T minItem = findMin();
        array[1] = array[currentSize--];
        percolateDown(1);
        return minItem;
    }

    /**
     * Establish heap order property from an arbitrary
     * arrangement of items. Runs in linear time.
     */
    private void buildHeap() {
        for(int i = currentSize/2; i > 0; i--) {
            percolateDown(i);
        }
    }

    /**
     * Test if the priority queue is logically empty.
     * @return true if empty, false otherwise.
     */
    public boolean isEmpty() {
        return currentSize == 0;
    }

    /**
     * Make the priority queue logically empty.
     */
    public void makeEmpty() {
        currentSize = 0;
    }

    private static final int DEFAULT_CAPACITY = 10;

    private int currentSize;      // Number of elements in heap
    private T[] array; // The heap array

    /**
     * Internal method to percolate down in the heap.
     * @param hole the index at which the percolate begins.
     */
    private void percolateDown(int hole) {
        int child;
        T tmp = array[ hole ];
        for(; hole*2 <= currentSize; hole = child) {
            child = hole*2;
            if(child != currentSize && array[child+1].compareTo(array[child]) < 0) {
                child++;
            }
            if(array[child].compareTo(tmp) < 0) {
                array[hole] = array[child];
            } else {
                break;
            }
        }
        array[hole] = tmp;
    }

}

测试

public class BinaryHeap {
    public static void main(String [] args) {
        int numItems = 10000;
        BinaryHeap<Integer> h = new BinaryHeap<>();
        int i;
        for(i = 37; i != 0; i = (i+37) % numItems) {
            h.insert(i);
        }
        for(i = 1; i < numItems; i++) {
            if(h.deleteMin() != i) {
                System.out.println("Oops! " + i);
            }
        }
    }
}
发布了570 篇原创文章 · 获赞 1179 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104457585
今日推荐