堆(优先队列)

二叉堆

二叉堆常常用于优先队列的实现。

堆是一个被完全填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入。

因为二叉堆是完全二叉树,所以可以使用数组表示,而不需要使用链表。(使用链表似乎代码实现方便点)

堆序性质

任意节点的值都小于它所有字节点的值

代码实现

/**
 * 二叉堆
 * 将堆数据存放在数组内,对自上而下,自左而右的数据依次放到数组中,数组索引从1开始,即array[0]不存放数据
 */
public class BinaryHeap {
    public BinaryHeap(){}

    public BinaryHeap(int x){
        currentSize++;
        array[currentSize]=x;
    }

    public BinaryHeap(int[] items){
        currentSize=items.length;
        array = new int[(currentSize+2)*11/10];
        int i=1;
        for(int item:items){
            array[i++]=item;
        }
        buildHeap();
    }

    public void insert(int x){
        if(currentSize==array.length-1) enlargeHeap(array.length*2+1);
        //hole代表空穴的位置
        int hole = ++currentSize;
        //空穴的位置上浮
        for(;hole>1 && x<(array[hole/2]);hole/=2){
            array[hole]=array[hole/2];
        }
        //最后空穴的位置为hole
        //将x放入空穴
        array[hole]=x;
    }

    public int findMin() throws Exception{
        if(isEmpty()) throw new Exception("堆为空");
        return array[1];
    }

    public int deleteMin()throws Exception{
        if(isEmpty()) throw new Exception("无法对空堆作删除操作");
        int min = findMin();
        //把最后一个元素放在首位,并减小堆大小currentSize
        array[1]=array[currentSize--];
        //然后调整堆第一个元素的位置
        percolateDown(1);
        return min;
    }

    public boolean isEmpty(){
        return currentSize==0;
    }

    public void makeEmpty(){
        currentSize=0;
    }

    private static final int DEFAULT_CAPCITY=10;

    private int currentSize=0;
    private int[] array;

    //对hole位置的元素做下沉操作
    private void percolateDown(int hole){
        int child=0;
        int tmp = array[hole];
        for(;hole*2<=currentSize;hole=child){
            child=hole*2;
            if(child!=currentSize && array[child+1]<array[child]) child++;
            if(array[child]<tmp) array[hole]=array[child];
            else break;
        }
        array[hole]=tmp;
    }

    private void buildHeap(){
        for (int i=currentSize/2;i>0;i--){
            percolateDown(i);
        }
    }

    private void enlargeHeap(int newSize){
        if(newSize<=array.length) return;
        int[] tmp = new int[newSize];
        for(int i=1;i<=currentSize;i++){
            tmp[i]=array[i];
        }
        array=tmp;
    }
}

 

posted @ 2017-05-05 11:00  且听风吟-wuchao  阅读(295)  评论(0编辑  收藏  举报