标签:
二叉堆,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