堆 - Heap

基本概念

堆是一種數(shù)據(jù)結構,定義為一棵完全二叉樹。假如用數(shù)組儲存堆結構,那么對于某個index為i的節(jié)點來說,它的左兒子的index為2*i+1,右兒子為2*i+2。
堆有兩種,小根堆和大根堆。對于小根堆,它的每個節(jié)點的值都小于該節(jié)點左右兒子的值。同理大根堆。

堆的操作

  • 堆化(heapify)
    O(n)
    表面上看heapify應該為O(nlogn),但是對于在第h-i層的節(jié)點來說,它最多的shiftdown深度為ishiftdown每一層的復雜度為O(1),而第h - i層一共有2 ^ {h - i}個節(jié)點, 所以整個heapify的時間復雜度為:
    2^{h - 1} *1 + 2^{h - 2} *2 +...+ 2^{1} *(h - 1) + h
    這是一個等比數(shù)列,通過將它乘以2,并做差,得到:
    2^{h+1} - 2 - h
    因為h = logn,所以heapify的時間復雜度為O(n)。
public class Heap {
    
    public void heapify(int[] A) {
        for (int i = (A.length - 2) / 2; i >= 0; i--) {
            shiftdown(A, i);
        }
    }
    
    public void shiftdown(int[] A, int k) {
        int n = A.length;
        int minIndex = k;
        int left = 2 * k + 1;
        int right = 2 * k + 2;
        if (left < n && A[left] < A[minIndex]) {
            minIndex = left;
        }
        if (right < n && A[right] < A[minIndex]) {
            minIndex = right;
        }
        if (minIndex != k) {
            int tmp = A[k];
            A[k] = A[minIndex];
            A[minIndex] = tmp;
            shiftdown(A, minIndex);
        }
    }
}
  • 添加
    O(logn)
  • 刪除
    O(logn)
  • 返回堆頂
    O(1)
public class minHeap {
    
    int[] A;
    int size;
    int maxSize;
    
    public minHeap(int n) {
        A = new int[n];
        size = 0;
        maxSize = n;
    }
    
    public void add(int x) {
        if (size == A.length) {
            return;
        }
        A[size] = x;
        shiftup(size);
        size++;
    }
    
    public int poll() {
        if (size == 0) {
            return Integer.MIN_VALUE;
        }
        size--;
        swap(0, size);
        shiftdown(0);
        return A[size];
    }
    
    public int peek() {
        if (size == 0) {
            return Integer.MIN_VALUE;
        }
        return A[0];
    }
    
    private void shiftdown(int k) {
        int minIndex = k;
        int left = 2 * k + 1;
        int right = 2 * k + 2;
        if (left < size && A[left] < A[minIndex]) {
            minIndex = left;
        }
        if (right < size && A[right] < A[minIndex]) {
            minIndex = right;
        }
        if (minIndex != k) {
            swap(minIndex, k);
            shiftdown(A, minIndex);
        }
    }
    
    private void shiftup(int k) {
        int parent = k / 2;
        if (A[k] < A[parent]) {
            swap[k, parent];
            shiftup(parent);
        }
    }
    
    private void swap(int a, int b) {
        int tmp = A[a];
        A[a] = A[b];
        A[b] = tmp;
    }
}
  • Java 內(nèi)置PriorityQueue
PriorityQueue<Integer> heap = new PriorityQueue<>(size, new Comparator<Integer>() {
        @Override
        public int compare {
                return a - b; // 小根堆 
                return b - a; // 大根堆
        }
});
heap.offer(); // 添加
heap.poll(); // 刪除
heap.peek(); // 返回堆頂元素,即最小或最大值

Lintcode 相關練習

Top k Largest Numbers II
K Closest Points

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 堆就是用數(shù)組實現(xiàn)的二叉樹,所以它沒有使用父指針或者子指針。堆根據(jù)“堆屬性”來排序,“堆屬性”決定了樹中節(jié)點的位置。...
    唐先僧閱讀 249,954評論 21 252
  • 什么是堆? 堆是滿足下面兩個條件的一種二叉樹 它是一棵完全二叉樹; 堆中每個節(jié)點的值都必須大于等于(大根堆)或者小...
    幣來幣往閱讀 500評論 0 0
  • 一:堆的介紹 Heap是一種數(shù)據(jù)結構具有以下的特點:1)完全二叉樹;2)heap中存儲的值是偏序; Min-hea...
    夢工廠閱讀 2,505評論 2 7
  • “堆”這種數(shù)據(jù)結構常用在“優(yōu)先級隊列”的實現(xiàn)上, 比如Java中的PriorityQueue。今天講講什么是堆,如...
    昵稱全尼馬被注冊了閱讀 1,038評論 0 1
  • 快月考的那段時間,天就想破了洞一樣,雨一下就是好幾天,體弱多病的自己自然是逃不過感冒的厄運,流涕,頭疼,發(fā)燒,各種...
    七汐子閱讀 348評論 0 1

友情鏈接更多精彩內(nèi)容