《Java數據結構》Java 堆結構原理和實現

前言

學習Java阻塞隊列的時候,瞭解到了ConcurrentLinkedQueue隊列使用了堆結構,就整理一下堆結構的邏輯

原理

堆是一顆滿二叉樹(除了最後一層的節點可以不滿,其他層都必須是滿的),元素存儲在數組中,頭結點必定是最大或者最小值(大小頂堆)。

結構圖

入隊邏輯:保證小頂堆不變

 

出隊邏輯:

代碼模擬實現

public class BinaryHeap {

    /**
     * 默認數組長度
     */
    private static final int DEFAULT_CAPACITY = 100;

    /**
     * 數組長度
     */
    private int currentSize;      // Number of elements in heap
    private Comparable[] array; // The heap array

    public BinaryHeap() {
        this(DEFAULT_CAPACITY);
    }

    public BinaryHeap(Comparable[] items) {
        currentSize = items.length;
        array = new Comparable[(currentSize + 2) * 11 / 10];

        int i = 1;
        for (Comparable item : items) {
            array[i++] = item;
        }
        buildHeap();
    }

    public BinaryHeap(int capacity) {
        currentSize = 0;
        array = new Comparable[capacity + 1];
    }

    public void insert(Comparable x) {
        // Percolate up
        int hole = ++currentSize;
        for (; hole > 1 && x.compareTo(array[hole / 2]) < 0; hole /= 2)
            array[hole] = array[hole / 2];
        array[hole] = x;
    }
    
    public Comparable findMin() {
        if (isEmpty())
            return null;
        return array[1];
    }

    public Comparable deleteMin() {
        if (isEmpty())
            return null;
        Comparable minItem = findMin();
        array[1] = array[currentSize--];
        percolateDown(1);

        return minItem;
    }

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

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

    public boolean isFull() {
        return currentSize == array.length - 1;
    }

    public void makeEmpty() {
        currentSize = 0;
    }

    private void percolateDown(int hole) {
        int child;
        Comparable tmp = array[hole];//保存變量

        for (; hole * 2 <= currentSize; hole = child) {
            child = hole * 2;//獲取左子樹結點
            //如果左子樹結點不是堆的長度並且左子樹大於右子樹的值
            if (child != currentSize && array[child + 1].compareTo(array[child]) < 0)
                child++;//child指向右子樹
            if (array[child].compareTo(tmp) < 0)//如果孩子比tmp小
                array[hole] = array[child];//交換值
            else
                break;
        }
        array[hole] = tmp;
    }
    
    public static void main(String[] args) {
        int numItems = 10;
        BinaryHeap h = new BinaryHeap(numItems);
        int i = 37;

        try {
            for (i = 37; i != 0; i = (i + 37) % numItems){
                h.insert(i);
            }

            System.out.println("插入數據之後展示=====================");
            for (int j=1;j<=h.currentSize;j++){
                System.out.print(h.array[j]+" ");
            }
            System.out.println();
            h.deleteMin();
            System.out.println("刪除數據之後展示=====================");
            for (int j=1;j<=h.currentSize;j++){
                System.out.print(h.array[j]+" ");
            }
            System.out.println();
        } catch (Exception e) {
            System.out.println("Overflow (expected)! " + i);
        }
    }
}

運行結果:

總結

堆是專門爲優先級排序準備的一種數據結構,最小/最大的值永遠在頂部,從底部獲取就可以保證優先級。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章