大頂堆和小頂堆


大頂堆:任意非葉子節點的值大於等於其子節點的值。

小頂堆:任意非葉子節點的值小於等於其子節點的值。

堆是完全二叉樹,所以可以直接用數組存儲。

堆初始化:

堆的初始化使用篩降法,從最后一個非葉子節點開始向下調整直到跟節點。需要建堆的數組長度為n,最后一個元素的下標為n-1,其父節點為 ((n-1) -  1)  >> 1

堆頂元素的刪除:

每次只能刪除堆頂元素,刪除完堆頂元素之后,將最后一個元素放在堆頂,此時的堆不滿足堆的性質,需要進行調整。

    /**
     * 向下調整
     *
     * @param i 要調整的編號
     */
    private void siftDown(int i) {
        // 如果父節點比任意一個子節點要大,需要調整,和子節點中較小的那個節點進行互換
        // 只有非葉子節點才需要調整
        int value = nums[i];
        while (2 * i + 1 < len) {
            int left = 2 * i + 1;
            int right = 2 * i + 2;
            // 有右節點,先比較兩個左右節點
            int minValueIdx = (right < len && nums[right] < nums[left]) ? right : left;
            // 子節點中比較小的和父節點比較
            if (nums[minValueIdx] < value) {
                // 需要調整
                nums[i] = nums[minValueIdx];
                i = minValueIdx;
            } else {
                // 節點i比孩子節點都小,不用再調整了
                break;
            }
        }
        nums[i] = value;
    }

向堆中添加元素:

每次向堆中添加元素時,直接將元素放在末尾,然后調整新放入元素的位置到正確的位置。

    public void add(int i) {
        if (len < nums.length) {
            nums[len] = i;
            siftUp(len);
            len++;
        }
    }

    /**
     * 向上調整
     *
     * @param i
     */
    private void siftUp(int i) {
        // i = 0時是根節點, 不需要再調整了
        int value = nums[i];
        while (i > 0) {
            int p = (i - 1) >> 1;
            if (nums[p] > value) {
                // 父節點更大, 需要調整
                nums[i] = nums[p];
                i = p;
            } else {
                break;
            }
        }
        nums[i] = value;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM