二叉堆,BinaryHeap,是二叉树中的常见的一种结构。通常以最大堆和最小堆的形式呈现。最大堆指的是父节点大于等于孩子节点的value值,也就是说对于最大堆而言,根元素是二叉堆最大的元素。最小堆的概念是与最大堆的概念是相似的。下图是最大堆的示意图:
二叉堆最显著的特征就是根元素是二叉树元素间最大的或者最小的。因此每次将二叉树最大或者最小的元素取出来,同时保证每次进行这样的操作后,剩下的元素依然可以保持二叉堆的性质,这样迭代这个过程,就可以完成排序的目的。
所以,进行堆排序的过程,首先就需要进行待排序元素的堆建立过程。这里以最大堆为例。
在建立最大堆的过程中,每插入一个元素,就要对元素进行一个上浮的操作。上浮是指对每个即将插入最大堆的元素进行判断,判断与当前元素与其父元素的大小关系,保持父元素与孩子元素之间的大小关系,重复这个过程,直到从根元素开始,所有的父元素和孩子元素都和二叉堆的定义保持一致。具体实现过程如下:
首先是最大堆的ADT:
template<class T>
class BinaryHeap
{
public:
    BinaryHeap(int capacity);
    ~BinaryHeap();
    void filterUp(int start);
    void Insert(T &data);
    T delHeap();
    void BuildHeap(vector<T> initArray);
    void displayHeap();
private:
    T *m_pData;
    int mCurSize;
    int mCapacity;
};然后是最大堆的建立过程:
template<class T>
void BinaryHeap<T>::filterUp(int start)
{
    int nIndex=start;
    T temp=m_pData[nIndex];
    int parentIndex=(int) start/2;
    while(nIndex>0)
    {
        if(m_pData[parentIndex]<temp)
        {
            m_pData[nIndex]=m_pData[parentIndex];
            nIndex=parentIndex;
            parentIndex=(int) nIndex/2;
        }
        else
            break;
    }
    m_pData[nIndex]=temp;
}
template<class T>
void BinaryHeap<T>::Insert(T &data)
{
    if(mCurSize>=mCapacity)
    {
        mCapacity*=2;
        mCurSize++;
    }
    m_pData[mCurSize]=data;
    filterUp(mCurSize);
}
完成了最大堆的建立,就可以进行最大元素的抽取了,将抽取的元素存起来,就可以进行迭代过程的排序了:
这里在抽取最大元素的抽取后,相应的元素个数就会减少一个,如果是把根元素的孩子结点移动到根元素的位置,然后从上往下进行这样的移动,这样不能很好的保持完全二叉树的性质。因此这里采取的小技巧是,将二叉树的最后一个元素移动到根元素的位置,这样仅仅只是交换value值,不需要频繁的移动元素的位置。以下是该过程的示意图:
第一步:
第二步:
这样就完成了最大元素的抽取过程了,然后下面是具体的实现过程:
template<class T>
T BinaryHeap<T>::delHeap()
{
    int parentIndex=0;
    T tempMax=m_pData[parentIndex];
    int nIndex=parentIndex*2+1;
    m_pData[parentIndex]=m_pData[mCurSize-1];
    T tempCur=m_pData[parentIndex];
    while((nIndex+1)<mCurSize)
    {
        if(tempCur>=m_pData[nIndex] && tempCur>=m_pData[nIndex+1])
        {
            break;
        }
        else
        {
            if(m_pData[nIndex]>m_pData[nIndex+1])
                {
                    m_pData[parentIndex]=m_pData[nIndex];
                    parentIndex=nIndex;
                }
            else
                {
                     m_pData[parentIndex]=m_pData[nIndex+1];
                     parentIndex=nIndex+1;
                }
                     nIndex=2*parentIndex+1;
        }
    }
    m_pData[parentIndex]=tempCur;
    if(mCurSize>1)
        mCurSize--;
    else
    {
        mCurSize--;
        cout<<"the heap size is zero!"<<endl;
    }
    return tempMax;
}以上就是关键的过程的代码,下面是完整过程的代码:
首先是二叉堆的头文件:
#ifndef BINARYHEAP_H_INCLUDED
#define BINARYHEAP_H_INCLUDED
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
template<class T>
class BinaryHeap
{
public:
    BinaryHeap(int capacity);
    ~BinaryHeap();
    void filterUp(int start);
    void Insert(T &data);
    T delHeap();
    void BuildHeap(vector<T> initArray);
    void displayHeap();
private:
    T *m_pData;
    int mCurSize;
    int mCapacity;
};
template<class T>
BinaryHeap<T>::BinaryHeap(int capacity)
{
    mCurSize=0;
    mCapacity=capacity;
    m_pData=new T[capacity];
}
template<class T>
BinaryHeap<T>::~BinaryHeap()
{
    mCurSize=0;
    mCapacity=0;
    delete []m_pData;
}
template<class T>
void BinaryHeap<T>::filterUp(int start)
{
    int nIndex=start;
    T temp=m_pData[nIndex];
    int parentIndex=(int) start/2;
    while(nIndex>0)
    {
        if(m_pData[parentIndex]<temp)
        {
            m_pData[nIndex]=m_pData[parentIndex];
            nIndex=parentIndex;
            parentIndex=(int) nIndex/2;
        }
        else
            break;
    }
    m_pData[nIndex]=temp;
}
template<class T>
void BinaryHeap<T>::Insert(T &data)
{
    if(mCurSize>=mCapacity)
    {
        mCapacity*=2;
        mCurSize++;
    }
    m_pData[mCurSize]=data;
    filterUp(mCurSize);
}
template<class T>
void BinaryHeap<T>::BuildHeap(vector<T> initArray)
{
    int nSize=initArray.size();
    if(nSize==0)
        return;
    else
    {
        for(int i=0;i<nSize;i++)
        {
            Insert(initArray.at(i));
            if(mCurSize<mCapacity)
                mCurSize++;
            else
            {
                mCapacity*=2;
                mCurSize++;
            }
        }
    }
}
template<class T>
T BinaryHeap<T>::delHeap()
{
    int parentIndex=0;
    T tempMax=m_pData[parentIndex];
    int nIndex=parentIndex*2+1;
    m_pData[parentIndex]=m_pData[mCurSize-1];
    T tempCur=m_pData[parentIndex];
    while((nIndex+1)<mCurSize)
    {
        if(tempCur>=m_pData[nIndex] && tempCur>=m_pData[nIndex+1])
        {
            break;
        }
        else
        {
            if(m_pData[nIndex]>m_pData[nIndex+1])
                {
                    m_pData[parentIndex]=m_pData[nIndex];
                    parentIndex=nIndex;
                }
            else
                {
                     m_pData[parentIndex]=m_pData[nIndex+1];
                     parentIndex=nIndex+1;
                }
                     nIndex=2*parentIndex+1;
        }
    }
    m_pData[parentIndex]=tempCur;
    if(mCurSize>1)
        mCurSize--;
    else
    {
        mCurSize--;
        cout<<"the heap size is zero!"<<endl;
    }
    return tempMax;
}
template<class T>
void BinaryHeap<T>::displayHeap()
{
    for(int i=0;i<mCurSize;i++)
    {
        cout<<m_pData[i]<<"---";
    }
    cout<<endl;
}
#endif // BINARYHEAP_H_INCLUDED
#include <iostream>
#include<cstdlib>
#include<ctime>
#include"BinaryHeap.h"
using namespace std;
int main()
{
    srand(unsigned(time(NULL)));
    vector<int> initArray;
    int data=rand()%100;
    int length=rand()%15;
    int cnt=0;
    while(cnt<length)
    {
        initArray.push_back(data);
        data=rand()%100;
        cnt++;
    }
    cout<<"待排序序列:"<<endl;
    for(int i=0;i<length;i++)
        cout<<initArray.at(i)<<"---";
    cout<<endl;
    BinaryHeap<int> heap(30);
    heap.BuildHeap(initArray);
    cout<<"建立好的最大堆:"<<endl;
    heap.displayHeap();
    int maxEle;
    vector<int> sortedArray;
    for(int i=0;i<initArray.size();i++)
    {
        maxEle=heap.delHeap();
        sortedArray.push_back(maxEle);
    }
    cout<<"排序完成的序列:"<<endl;
    for(int i=0;i<sortedArray.size();i++)
    {
        cout<<sortedArray.at(i)<<"---";
    }
        cout<<endl;
    cout << "Hello world!" << endl;
    return 0;
}
原文:http://blog.csdn.net/mao19931004/article/details/51236246