数据结构--二叉堆与堆排序

来源:互联网 发布:读懂中国经济数据 编辑:程序博客网 时间:2024/05/31 19:40

  • 二叉堆的概念

二叉堆,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;}


然后结果如下:




0 0
原创粉丝点击