1. 程式人生 > 實用技巧 >小根堆的建立及siftDown與siftUp演算法

小根堆的建立及siftDown與siftUp演算法

//最大堆的構建、結點的插入和刪除與此完全類似
#include<iostream>
using namespace std;

class MinHeap
{
public:
    int* heap;//存放最小堆中元素的陣列
    int maxHeapSize;//最小堆最多允許元素個數
    int currentSize;//最小堆中當前元素個數
public:
    MinHeap(int sz){
        maxHeapSize=sz;
        heap=new int[maxHeapSize];
        currentSize=0;
    }
    MinHeap(
int arr[],int n,int sz){ //陣列傳參後,傳的是指標,sizeof(arr)不能計算出該陣列有多少個位元組,而是該指標變數所佔位元組, maxHeapSize=sz; //在這裡sizeof(arr)=4 heap=new int[maxHeapSize]; for(int i=0;i<n;i++){ heap[i]=arr[i]; } currentSize=n; int currentPos=(currentSize-1-1
)/2;//堆(完全二叉樹)的最後一個節點的父節點 while(currentPos>=0){ siftDown(currentPos,currentSize-1); currentPos--; } } void siftDown(int start,int m) //m接收的實參是堆(完全二叉樹)的最後一個節點 { int i=start,j=2*i+1; //i指父結點,j指左孩子結點 int temp=heap[i]; while(j<=m) {
if(j<m&&heap[j]>heap[j+1]) { j++; } if(temp<=heap[j]) { break; } else { heap[i]=heap[j]; i=j; j=2*j+1; } } heap[i]=temp; } void siftUp(int start) { int j=start,i=(j-1)/2; //j可為左孩子也可右孩子,i指父結點 int temp=heap[j]; while(j>0) { if(heap[i]<=temp) { break; } else { heap[j]=heap[i]; j=i; i=(i-1)/2; } } heap[j]=temp; } bool Insert(int x) { if(currentSize==maxHeapSize) { return false; } heap[currentSize]=x; siftUp(currentSize); currentSize++; return true; } int RemoveMin() { if(!currentSize) { return false; } int x=heap[0]; heap[0]=heap[currentSize-1]; currentSize--; siftDown(0,currentSize-1); return x; } void show(){ for(int i=0;i<currentSize;i++){ cout<<heap[i]<<" "; } } }; int main() { int arr[]={53,17,78,9,45,65,87,23}; int n=sizeof(arr)/sizeof(int); MinHeap minHeap(arr,n,50); minHeap.show(); cout<<endl; minHeap.Insert(1);//插入1 minHeap.show(); cout<<endl; cout<<"刪除的堆頂元素:"<<minHeap.RemoveMin()<<endl;//刪除堆頂元素,並返回原堆頂元素 minHeap.show(); cout<<endl; return 0; } //9 17 65 23 45 78 87 53 //1 9 65 17 45 78 87 53 23 //刪除的堆頂元素:1 //9 17 65 23 45 78 87 53