數據結構 ||大根堆的實現

建堆(建大堆)

  • 算法思想
  • 1.將指定數組的相關屬性拷貝給目標堆
  • 2.針對堆數組向滿足堆性質的方向調整
  • 代碼實現
    void HeapInit(Heap<int>* heap,const T* array,int size){
      heap->_array=new T[size];
      heap->_size=size;
      memcpy(heap->_array,array,sizeof(T)*size);
      //用來將指定數組中的內容拷貝到堆數組空間中
      _CreateHeap(heap->_array,heap->_size); 
    }

    void _CreateHeap(T* array,int size){
      for(int i=(size-2)/2;i>=0;i--){
        AdjustDown(array,size,i);
      }
    }

向下調整

  • 算法思想

  • 1.拿到第一個非葉子結點的下標,

  • 2.計算出左右孩子結點的下標,檢查合法性

  • 3.找出左右孩子中值較大的結點並與其父結點值比較大小

  • 4.若左右孩子中較大孩子的結點值小於其父親結點的值則不需要調整

  • 5.若左右孩子中較大孩子的結點值大於其父親結點的值則將較大孩子和父結點的值進行交換

  • 代碼實現

    void AdjustDown( T* array,int size,int parent){
      while(1){
        int left=2*parent+1;
        if(left>=size){
          return;
        }
        int max=left;
         int right=2*parent+2;     
        if(right<size && array[left]<array[right]){
          max=right;
        }

        if(array[parent] >=  array[max]){
          return;
        }

        Swap(array+parent,array+max);
        parent=max;
      }
    }

向上調整

  • 算法思想

  • 1.拿到孩子結點值的下標,檢查其合法性

  • 2.根據孩子的下標求出父親結點的下標 [root]=[child-1]/2

  • 3.判斷下標child和下標root值對應的值的大小關係

  • 4.若插入結點的值符合堆的性質則結束調整

  • 5.若插入結點的值不符合堆的性質,則需要其與其父節點進行值的交換

  • 6.一直調整到堆數組符合堆的性質爲止

  • 代碼實現

    void AdjustUp(T* array,int  size,int child){

      while(child!=0){
        
        if(child>size){
          return;
        }
        int root=(child-1)/2;

        if(array[root]>=array[child]){
          return;
        }

        Swap(array+root,array+child);
        child=root;
      }
    }

堆的插入

  • 算法思想
  • 1.將新的值插入到堆的尾部
  • 2.若其不滿足堆的性質,對其進行向上調整
  • 3.若其滿足堆的性質,結束調整
  • 代碼實現
   void  HeapPush(Heap<T>* heap,T val){
      heap->_array[heap->_size]=val;
      heap->_size++;
      AdjustUp(heap->_array,heap->_size,heap->_size-1);
    }

堆的刪除

  • 算法思想
  • 1.交換堆頂元素和最後一個元素的值
  • 2.減少一個有效訪問計數
  • 3.從堆頂開始繼續向下調整,直到符合堆的性質
  • 代碼實現
   void HeapPop(Heap<T>* heap){
     if(heap==nullptr){
       return;
     }

     Swap(heap->_array,&heap->_array[--heap->_size]);

     AdjustDown(heap->_array,heap->_size,0);
   }

整體實現

#pragma once 
#include<iostream>
#include<memory.h>

using namespace std;

template <class T>

class Heap{
  public:
    Heap(int size=T())
      :_array(nullptr)
       ,_size(size)
  {}

    void HeapInit(Heap<int>* heap,const T* array,int size){
      heap->_array=new T[size];
      heap->_size=size;
      memcpy(heap->_array,array,sizeof(T)*size);
      //用來將指定數據中的內容拷貝到堆數組空間中
      _CreateHeap(heap->_array,heap->_size); 
    }




    void PrintHeap(const Heap<T>* heap){
      if(heap==nullptr){
        return;
      }

      for(int i=0;i<heap->_size;i++){
        cout<<heap->_array[i]<< " ";
      }
      cout<<endl;
    }


   void  HeapPush(Heap<T>* heap,T val){
      heap->_array[heap->_size]=val;
      heap->_size++;
      AdjustUp(heap->_array,heap->_size,heap->_size-1);
    }

   void HeapPop(Heap<T>* heap){
     if(heap==nullptr){
       return;
     }

     Swap(heap->_array,&heap->_array[--heap->_size]);

     AdjustDown(heap->_array,heap->_size,0);
   }

   void Heap_Find(const Heap<T>* heap){
     int val=0;
    
     cout<<"請輸入您要差找的值:";
     cin>>val;
     bool   index=false;

     for(int i=0;i<heap->_size;i++){
       if(heap->_array[i]==val){
         index=true;
         break;
       }
     }

     if(index==false){
       cout<<"您所要查找的值不存在!"<<endl;
       return;
     }

     cout<<"您所要查找的值在該堆中!"<<endl;

   }


   T& Heap_Top(const Heap<T>* heap){
     cout<<heap->_array[0];
   }


   //堆排序
   void Heap_Sort(T* array,int size){
     _CreateHeap(array,size);
     for(int i=0;i<size;i++){
       Swap(array,array+(size-1-i));
       AdjustDown(array,size-1-i,0);
     }
   }

   
   void HeapModify(Heap<T>* heap){
     int val;
     cout<<"請輸入要修改的值:";
     cin>>val;

     int  index=-1;

     for(int i=0;i<heap->_size;i++){
       if(heap->_array[i]==val){
         index=i;
         break;
       }
     }

     if(index==-1){
       cout<<"您所要修改的值不存在!"<<endl;
       return;
     }

     cout<<"請輸入修改後的值:";
     cin>>val;
     heap->_array[index]=val;

     AdjustUp(heap->_array,heap->_size,index);
   }
  private:
    void _CreateHeap(T* array,int size){
      for(int i=(size-2)/2;i>=0;i--){
        AdjustDown(array,size,i);
      }
    }

    void Swap(T* a,T* b){
      T tmp=*a;
      *a=*b;
      *b=tmp;
    }

    void AdjustDown( T* array,int size,int parent){
      while(1){
        int left=2*parent+1;
        if(left>=size){
          return;
        }



        int max=left;
         int right=2*parent+2;     
        if(right<size && array[left]<array[right]){
          max=right;
        }

        if(array[parent] >=  array[max]){
          return;
        }

        Swap(array+parent,array+max);
        parent=max;
      }
    }


    void AdjustUp(T* array,int  size,int child){

      while(child!=0){
        
        if(child>size){
          return;
        }
        int root=(child-1)/2;

        if(array[root]>=array[child]){
          return;
        }

        Swap(array+root,array+child);
        child=root;
      }
    }
  private:
    T* _array;
    int _size;
};

測試代碼

#include"BinaryHeap.hpp"

void TestHeap(){
  int array[]={1,2,3,4,5,6,7,8,9};
  size_t size=sizeof(array)/sizeof(array[0]);
  Heap<int> heap;
  heap.HeapInit(&heap,array,size);
  heap.PrintHeap(&heap);
  heap.HeapPush(&heap,100);
  heap.PrintHeap(&heap);
  heap.HeapPop(&heap);
  heap.PrintHeap(&heap);

  heap.HeapModify(&heap);
  heap.PrintHeap(&heap);

  heap.Heap_Find(&heap);
  heap.Heap_Sort(array,size);
  heap.PrintHeap(&heap);
}

int main(){
  TestHeap();
  return 0;
}

測試結果展示

在這裏插入圖片描述

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