堆,是一種完全二叉樹。而且在這顆樹中,父節點必然大於(對於小頂堆為小於)子節點。
關於樹的概念不了解可以看這里:http://www.cnblogs.com/HongYi-Liang/p/7231440.html
由於堆是一種完全二叉樹,很適合保存為數組的形式。如下圖示意的堆,紅色數字為數組索引,黑色數字為數組的值,那么這個堆保存為數組的形式:heap={9,8,5,6,7,1,4,0,3,2};
值得注意的是,在堆中,若設父親的索引為i,左兒子的索引剛好等於2i,而右兒子的索引等於2i+1。這個公式會大量地出現在下邊的程序中。
關鍵概念:
大頂堆:樹根元素為最大值往葉子遞減,(父節點總是大於子節點)
小頂堆:樹根元素為最小值往葉子遞增,(父節點總是小於子節點)
下為一個大頂堆的示意圖,父節點總是大於子節點
在下面的程序中,C將以大頂堆的形式編寫,C++以小頂堆的形式編寫。
C語言
程序源碼:
本例子為大頂堆,包含4個文件(如下圖)
MaxHeap.c

#include "MaxHeap.h" bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length); bool MaxHeapDesturct(MaxHeap *heap); bool MaxHeap_getSize(MaxHeap *heap); bool MaxHeap_isFull(MaxHeap *heap); bool MaxHeap_isEmpty(MaxHeap *heap); void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b); void MaxHeap_floating(MaxHeap *heap,int index); void MaxHeap_sink(MaxHeap *heap, int index); bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data); bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data); bool MaxHeap_pop(MaxHeap *heap,int index); void MaxHeap_printfAll(MaxHeap *heap); bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length) { int i; if(NULL != heap->iDatas) { return false; } heap->iHeapCapacity=length; heap->iHeapSize=0; heap->iDatas = (MAXHEAP_ELEM*)malloc(sizeof(MAXHEAP_ELEM)*length); for(i=0;i<length;i++) { MaxHeap_push(heap,buff[i]); } return true; } bool MaxHeapDesturct(MaxHeap *heap) { if(NULL == heap->iDatas) { return false; } free(heap->iDatas); return true; } bool MaxHeap_getSize(MaxHeap *heap) { return heap->iHeapSize; } bool MaxHeap_isFull(MaxHeap *heap) { if(heap->iHeapCapacity == heap->iHeapSize) { return true; } return false; } bool MaxHeap_isEmpty(MaxHeap *heap) { if(0 == heap->iHeapSize) { return true; } return false; } void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b) { MAXHEAP_ELEM temp; temp=*a; *a=*b; *b=temp; } void MaxHeap_floating(MaxHeap *heap,int index) { int i; for(i=index;i>0;i=(int)(i*0.5)) { if(heap->iDatas[i-1] > heap->iDatas[(int)(i*0.5-1)] ) { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[(int)(i*0.5-1)]); } else { break; } } } void MaxHeap_sink(MaxHeap *heap, int index) { int i=index; while(i*2<=heap->iHeapSize) { if(heap->iDatas[i-1] < heap->iDatas[i*2-1])//it compare to left child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2-1]); if(i*2+1<=heap->iHeapSize && heap->iDatas[i-1] < heap->iDatas[i*2])//it compare to right child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2]); } /*index*/ i=i*2; } else if(i*2+1<=heap->iHeapSize && heap->iDatas[i-1] < heap->iDatas[i*2])//it compare to right child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2]); i=i*2+1; } else { break; } } } bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data) { if( MaxHeap_isFull(heap)) return false; heap->iDatas[heap->iHeapSize]=data; heap->iHeapSize++; MaxHeap_floating(heap,heap->iHeapSize); return true; } bool MaxHeap_pop(MaxHeap *heap,int index) { if(MaxHeap_isEmpty(heap)) return false; heap->iDatas[index]=heap->iDatas[heap->iHeapSize-1]; heap->iHeapSize--; MaxHeap_sink(heap,index+1); return true; } void MaxHeap_printfAll(MaxHeap *heap) { int i; printf("heap:"); for( i=0;i<heap->iHeapSize;i++) { printf("%d ",heap->iDatas[i]); } printf("\r\n"); }
MaxHeap.h

#ifndef __MAXHEAP_H #define __MAXHEAP_H #include <stdlib.h> #include <stdio.h> #include "Mystdbool.h" typedef int MAXHEAP_ELEM; typedef struct { int iHeapCapacity; int iHeapSize; MAXHEAP_ELEM *iDatas; }MaxHeap; bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length); bool MaxHeapDesturct(MaxHeap *heap); bool MaxHeap_getSize(MaxHeap *heap); bool MaxHeap_isFull(MaxHeap *heap); bool MaxHeap_isEmpty(MaxHeap *heap); void MaxHeap_swap(MAXHEAP_ELEM *a,MAXHEAP_ELEM *b); void MaxHeap_floating(MaxHeap *heap,int index); void MaxHeap_sink(MaxHeap *heap, int index); bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data); bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data); bool MaxHeap_pop(MaxHeap *heap,int index); void MaxHeap_printfAll(MaxHeap *heap); #endif
Mystdbool.h(僅用於聲明布爾類)

#ifndef _MYSTDBOOL_H #define _MYSTDBOOL_H typedef enum Bool { false=0, true, }bool; #endif
main.c

#include "MaxHeap.h" int main() { /*int buffer[10]={9,8,7,6,5,4,3,2,1,0};*/ int buffer[10]={0,1,2,3,4,5,6,7,8,9}; MaxHeap heap={0}; MaxHeapConstructByBuffer(&heap,buffer,10); MaxHeap_printfAll(&heap); MaxHeap_pop(&heap,0); MaxHeap_printfAll(&heap); MaxHeap_pop(&heap,0); MaxHeap_printfAll(&heap); system("pause"); return 0; }
運行結果:
源碼詳解:
上浮:floating(int index)
- 將堆第index個元素與它的父親比較,若小於它的父親,則與它父親交換數值。
- 上述過程如果發生,則把它繼續上浮。
void MaxHeap_floating(MaxHeap *heap,int index) { int i; for(i=index;i>0;i=(int)(i*0.5)) { if(heap->iDatas[i-1] > heap->iDatas[(int)(i*0.5-1)] ) { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[(int)(i*0.5-1)]); } else { break; } } }
添加元素:push(T data)
- 把元素添加到堆的最后。
- 並使用上浮方法把堆的最后一個元素上浮。
bool MaxHeap_push(MaxHeap *heap,MAXHEAP_ELEM data) { if( MaxHeap_isFull(heap)) return false; heap->iDatas[heap->iHeapSize]=data; heap->iHeapSize++; MaxHeap_floating(heap,heap->iHeapSize); return true; }
構建堆:MaxHeapConstructByBuffer()
- 用malloc為數據申請空間。
- 一個一個地將buff中的數據push()到堆中。
bool MaxHeapConstructByBuffer(MaxHeap *heap,MAXHEAP_ELEM buff[],int length)
{
int i; if(NULL != heap->iDatas) { return false; } heap->iHeapCapacity=length; heap->iHeapSize=0; heap->iDatas = (MAXHEAP_ELEM*)malloc(sizeof(MAXHEAP_ELEM)*length); for(i=0;i<length;i++) { MaxHeap_push(heap,buff[i]); } return true; }
下沉:
- 從根開始,用父節點與左子節點比較。若父節點大於左子,則交換它們的值
- 用父節點與右子節點比較。若父節點大於右子,則交換它們的值。
- 若上述情況發生了,則繼續下沉,直到無法下沉為止。
void MaxHeap_sink(MaxHeap *heap, int index) { int i=index; while(i*2<=heap->iHeapSize) { if(heap->iDatas[i-1] < heap->iDatas[i*2-1])//it compare to left child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2-1]); if(i*2+1<=heap->iHeapSize && heap->iDatas[i-1] < heap->iDatas[i*2])//it compare to right child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2]); } /*index*/ i=i*2; } else if(i*2+1<=heap->iHeapSize && heap->iDatas[i-1] < heap->iDatas[i*2])//it compare to right child { MaxHeap_swap(&heap->iDatas[i-1],&heap->iDatas[i*2]); i=i*2+1; } else { break; } } }
刪除元素:pop(int index)
- 把堆的第index個元素刪除,並把堆的最后一個元素放到index處。
- 把堆的第index個元素下沉
bool MaxHeap_pop(MaxHeap *heap,int index) { if(MaxHeap_isEmpty(heap)) return false; heap->iDatas[index]=heap->iDatas[heap->iHeapSize-1]; heap->iHeapSize--; MaxHeap_sink(heap,index+1); return true; }
C++
程序源碼:
本例子為小頂堆,包含2個文件(如下圖)
MyMinHeap.h:
此文件中為小頂堆的類模板。

#ifndef __MYMINHEAP_H #define __MYMINHEAP_H #include <iostream> #include <vector> using namespace std; template <typename T> class MyMinHeap { public: MyMinHeap(T buff[],int length); MyMinHeap(int capacity); virtual ~MyMinHeap(); int getSize(); bool isFull(); bool isEmpty(); void swap(vector<T> &vec,int i,int j); void floating(int index); void sink(int index); bool push(T data); bool pop(int index); //transval void printfAll(); private: int m_iHeapCapacity; int m_iHeapSize; vector<T> m_vecData; }; template <typename T> MyMinHeap<T>::MyMinHeap(T buff[],int length) { m_iHeapCapacity=length; m_iHeapSize=0; m_vecData.resize(length); for(int i=0;i<length;i++) { push(buff[i]); } } template <typename T> MyMinHeap<T>:: MyMinHeap(int capacity) { m_iHeapCapacity=capacity; m_iHeapSize=0; m_vecData.resize(capacity); } template <typename T> MyMinHeap<T>::~MyMinHeap() { } template <typename T> int MyMinHeap<T>::getSize() { return m_iHeapSize; } template <typename T> bool MyMinHeap<T>::isFull() { if(m_iHeapSize>=m_iHeapCapacity) { return true; } return false; } template <typename T> bool MyMinHeap<T>::isEmpty() { if(m_iHeapSize==0) return true; return false; } template <typename T> void MyMinHeap<T>::swap(vector<T> &vec,int i,int j) { T temp = vec[i]; vec[i]=vec[j]; vec[j]=temp; } template <typename T> void MyMinHeap<T>::floating(int index) { T temp; for(int i=index;i>0;i*=0.5) { if(m_vecData[i-1]<m_vecData[i*0.5-1] ) { swap(m_vecData,i-1,i*0.5-1); } else { break; } } } template <typename T> void MyMinHeap<T>::sink(int index) { int i=index; while(i*2<=m_iHeapSize) { if(m_vecData[i-1]>m_vecData[i*2-1])//it compare to left child { swap(m_vecData,i-1,i*2-1); if(i*2+1<=m_iHeapSize && m_vecData[i-1]>m_vecData[i*2])//it compare to right child { swap(m_vecData,i-1,i*2); } /*index*/ i=i*2; } else if(i*2+1<=m_iHeapSize && m_vecData[i-1]>m_vecData[i*2])//it compare to right child { swap(m_vecData,i-1,i*2); i=i*2+1; } else { break; } } } template <typename T> bool MyMinHeap<T>::push(T data) { if(isFull()) return false; m_vecData[m_iHeapSize]=data; m_iHeapSize++; floating(m_iHeapSize); return true; } template <typename T> bool MyMinHeap<T>::pop(int index) { if(isEmpty()) return false; m_vecData[index]=m_vecData[m_iHeapSize-1]; m_iHeapSize--; sink(index+1); return true; } template <typename T> void MyMinHeap<T>::printfAll() { cout<<"heap:"; for(int i=0;i<m_iHeapSize;i++) { cout<<m_vecData[i]<<" "; } cout<<endl<<endl; } #endif
main.h:
主程序用於測試運行。

#include <iostream> #include "MyMinHeap.h" using namespace std; int main() { int buffer[10]={9,8,7,6,5,4,3,2,1,0}; MyMinHeap<int> heap(buffer,10); heap.printfAll(); heap.pop(1); heap.printfAll(); heap.push(1); heap.printfAll(); system("pause"); return 0; }
運行結果:
源碼詳解:
上浮:floating(int index)
- 將堆第index個元素與它的父親比較,若小於它的父親,則與它父親交換數值。
- 上述過程如果發生,則把它繼續上浮。
template <typename T> void MyMinHeap<T>::floating(int index) { T temp; for(int i=index;i>0;i*=0.5) { if(m_vecData[i-1]<m_vecData[i*0.5-1] ) { swap(m_vecData,i-1,i*0.5-1); } else { break; } } }
添加元素:push(T data)
- 把元素添加到堆的最后。
- 並使用上浮方法把堆的最后一個元素上浮。
template <typename T> bool MyMinHeap<T>::push(T data) { if(isFull()) return false; m_vecData[m_iHeapSize]=data; m_iHeapSize++; floating(m_iHeapSize); return true; }
構造函數:使用數組構建堆:
連續使用push()把buff中所有元素一個一個地加入堆中。
template <typename T> MyMinHeap<T>::MyMinHeap(T buff[],int length) { m_iHeapCapacity=length; m_iHeapSize=0; m_vecData.resize(length); for(int i=0;i<length;i++) { push(buff[i]); } }
下沉:
- 從根開始,用父節點與左子節點比較。若父節點大於左子,則交換它們的值
- 用父節點與右子節點比較。若父節點大於右子,則交換它們的值。
- 若上述情況發生了,則繼續下沉,直到無法下沉為止。
template <typename T> void MyMinHeap<T>::sink(int index) { int i=index; while(i*2<=m_iHeapSize) { if(m_vecData[i-1]>m_vecData[i*2-1])//it compare to left child { swap(m_vecData,i-1,i*2-1); if(i*2+1<=m_iHeapSize && m_vecData[i-1]>m_vecData[i*2])//it compare to right child { swap(m_vecData,i-1,i*2); } /*index*/ i=i*2; } else if(i*2+1<=m_iHeapSize && m_vecData[i-1]>m_vecData[i*2])//it compare to right child { swap(m_vecData,i-1,i*2); i=i*2+1; } else { break; } } }
刪除元素:pop(int index)
- 把堆的第index個元素刪除,並把堆的最后一個元素放到index處。
- 把堆的第index個元素下沉
template <typename T> bool MyMinHeap<T>::pop(int index) { if(isEmpty()) return false; m_vecData[index]=m_vecData[m_iHeapSize-1]; m_iHeapSize--; sink(index+1); return true; }