1. 程式人生 > >最大堆、最小堆定義及其C++程式碼實現

最大堆、最小堆定義及其C++程式碼實現

資料:https://blog.csdn.net/guoweimelon/article/details/50904346
但是它的最大堆刪除部分的程式碼有問題,詳見連結裡的評論區

定義
堆首先必須是一棵完全二叉樹
最大堆:完全二叉樹,父節點的值不小於子節點的值
最小堆:完全二叉樹,父節點的值不大於子節點的值
在這裡插入圖片描述

用陣列儲存上圖所示的最大堆
對於下標為 i ( 1

i n ) i (1 \leq i \leq n) 的節點:
父節點: i / 2
i/2
,若 i = 1 i=1 ,則i是根節點
左子節點:2i,如果 2 i
> n 2i > n
,則不存在左子節點
右子節點:2i+1,如果 2 i + 1 > n 2i+1 > n ,則不存在右子節點

最大堆的插入:時間複雜度O(logn)
肯定在陣列末尾加入該數字,然後和父節點進行比較,balabala,也就是節點上浮操作。

最大堆的刪除:時間複雜度O(logn)
刪除根節點元素,用陣列的最後一個元素來頂替,然後進行節點下沉

最大堆的建立:
方法一:可以通過最大堆的插入演算法進行構建,即從空堆開始,依次插入數字。該方法的時間複雜度為O(n log n)
方法二:將時間複雜度降低到O(n),先將所有資料放入,然後逐個調整

struct MaxHeap{
    int heap[100];
    int currentSize=0;
    int maxSize=100;
    // 最大堆的建立,採用方法二
    void HeapInit(int a[],int n){
       currentSize = n;
       for(int i=0;i<n;i++)
        heap[i] = a[i];
       for(int i= (currentSize-2)/2; i>=0; i--){
         SiftDown(i);
       }
    }
    void SiftDown(int index){
         int cur = index;
         int son = 2*index+1;
         int tmp = heap[index];
         while(son < currentSize){
           if(son<currentSize-1 && heap[son]<heap[son+1])
                son++;
           if(tmp < heap[son]){
             heap[cur] = heap[son];
             cur = son;
             son = 2* cur + 1;
           }else
           break;

         }
         heap[cur] = tmp;

    }
  // 插入一個元素
    void HeapInsert(int value){
         if(currentSize == maxSize) return;
         currentSize++;
         int index = currentSize-1;
         while(index>0){
            if( heap[(index-1)/2] >= value) break;
            heap[index] = heap[(index-1)/2];
            index = (index-1)/2;
         }
         heap[index] = value;

    }
    // 刪除一個元素
    int HeapDelete(){
         if(currentSize==0) return -1;
         int maxValue = heap[0];
         heap[0] = heap[currentSize-1];
         currentSize--;
         SiftDown(0);
         return maxValue;
    }
};