大顶堆的C++模板实现及二叉堆的简介
2016-10-15 17:21
746 查看
何为二叉堆?
二叉堆是一种特殊的堆,二叉堆是完全二叉树或者近似完全二叉树。二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左右子树都是一个二叉堆。当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆(大顶堆)。
当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆(小顶堆)。
根据二叉树的性质,可得:
1. 如果根节点在数组的位置是1,第n个位置的子节点分别在2n和2n+1,第n个位置的双亲节点在[i/2]。因此,第1个位置的子节点在2和3。
2. 如果根节点在数组的位置是0,第n个位置的子节点分别在2n+1和2n+2,第n个位置的双亲节点在[(i-1)/2]。因此,第0个位置的子节点在1和2。
二叉堆一般用数组来表示,得益于数组的随机存储能力,我们能够很快确定堆中节点的父节点和子节点。
![](http://images2015.cnblogs.com/blog/610439/201601/610439-20160131124019943-624638029.png)
在本文中,我们主要介绍大顶堆的C++模板实现过程,以根节点在0位置存储为例。
二叉堆的具体实现
1. 二叉堆的抽象数据类型
/*大顶堆类定义*/ template <typename T> class MaxHeap { public: MaxHeap(int cap); ~MaxHeap(); bool insert(T val); //往二叉堆中插入元素 bool remove(T val); //从二叉堆中删除元素 void print(); //打印二叉堆 T getTop(); //获取堆顶元素 bool creatMaxHeap(T a[],int size);//根据指定数组创建大顶堆 private: int ArraySize; //数组的大小 int size; //堆的大小,数组中有效元素的个数 T* maxheap; //底层数组 //从index节点往根节点调整堆 void filterUp(int index); //从begin节点向end节点调整堆 void filterDown(int begin,int end); };
2. 构造函数与析构函数
/*构造函数*/ template <typename T> MaxHeap<T>::MaxHeap(int cap) { ArraySize = cap; //初始化数组的大小 size = 0; maxheap = new T[ArraySize]; //开辟空间 }; /*析构函数*/ template <typename T> MaxHeap<T>::~MaxHeap() { delete []maxheap; //释放空间 }
3. 大顶堆的插入
在数组的最末尾插入节点,然后自上而下地调整子节点与父节点的位置:比较当前节点与父节点的大小,若不满足大顶堆的性质,则交换两节点。时间复杂度为O(log n)。
![](http://images2015.cnblogs.com/blog/610439/201601/610439-20160131124027489-1257653323.png)
/*从下往上调整堆--插入元素时使用*/ template <typename T> void MaxHeap<T>::filterUp(int index) { //记录下当前节点 T value = maxheap[index]; while(index>0) { //得到其双亲节点 int indexparent = (index - 1) / 2; if(value < maxheap[indexparent]) break; else //交换两节点 { //新节点被其父节点覆盖 maxheap[index] = maxheap[indexparent]; //记录下新节点的位置 index = indexparent; } } //给新节点赋值 maxheap[index] = value; }; /*插入元素*/ template<typename T> bool MaxHeap<T>::insert(T val) { if(ArraySize == size) //如果数组放不下 return false; maxheap[size] = val; //数组末尾放入新节点 filterUp(size); //自下而上调整节点 size++; //堆的元素数量加1 return true; };
实际编码过程中,我们不进行节点的交换,我们直接使用父节点覆盖当前节点,然后记录新节点的位置,最后直接把新节点放入它最后的位置即可。
4. 大顶堆的删除
堆删除节点的过程:用数组最末尾节点覆盖被删结点,然后数组的有效元素(即堆中的元素)数量减1,再由该节点从上到下调整二叉堆。
/*从上到下调整堆--删除元素时使用*/ template <typename T> void MaxHeap<T>::filterDown(int current,int end) { int child = current * 2 + 1; //当前结点的左孩子 T value = maxheap[current]; //保存当前节点 while(child <= end) { //选出两个孩子中较大的孩子 if(child < end && maxheap[child] < maxheap[child + 1]) child++; if(value > maxheap[child])//无需调整 break; else { maxheap[current] = maxheap[child]; //孩子节点覆盖当前节点 current = child; //当前节点为较大的孩子节点 child = child * 2 + 1; //child重新指向当前节点的左孩子节点 } } maxheap[current] = value; //找到合理地位置后 赋值 }; /*删除元素*/ template <typename T> bool MaxHeap<T>::remove(T key) { if(size == 0) return false; int index; //被删除元素的下标 for(index = 0; index < size; index++) { if(maxheap[index] == key) break; //找到被删元素的下标 } if(index == size) return false; //数组中没有要删除的元素 //使用数组最后一个元素来代替该被删除元素 maxheap[index] = maxheap[size - 1]; //覆盖完成后 从上到下调整堆 filterDown(index,size--); return true; };
5. 其他操作
/*获取堆顶元素*/ template <typename T> T MaxHeap<T>::getTop() { if(size != 0) return maxheap[0]; }; /*打印大顶堆*/ template <typename T> void MaxHeap<T>::print() { for(int i=0; i<size; i++) cout << maxheap[i] << " "; cout << endl; }; /*根据指定数组创建大顶堆*/ template <typename T> bool MaxHeap<T>::creatMaxHeap(T a[],int size) { if(ArraySize < size) return false; for(int i=0; i<size; i++) insert(a[i]); return true; };
6. 测试代码
int main() { MaxHeap<int> heap1(11); //逐个元素创建大顶堆 for(int i=0; i<10; i++) heap1.insert(i); cout << "堆顶元素为:" << heap1.getTop() << endl; heap1.print(); /*从堆中删除元素5*/ heap1.remove(5); heap1.print(); //根据指定数组创建大顶堆*/ int array[10] = { 1,2,3,4,5,6,7,8,9,10 }; MaxHeap<int> heap2(11); heap2.creatMaxHeap(array,10); cout << "堆顶元素为:" << heap2.getTop() << endl; heap2.print(); return 0; }
7. 输出结果
堆顶元素为:9 9 8 5 6 7 1 4 0 3 2 9 8 4 6 7 1 2 0 3 堆顶元素为:10 10 9 6 7 8 2 5 1 4 3
ok,all right.
相关文章推荐
- 栈的简介与C++模板实现
- 栈的简介及C++模板实现
- 队列的简介与C++模板实现
- [置顶] c++实现的二叉堆::模板
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 数据结构图文解析之:树的简介及二叉排序树C++模板实现.
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 数据结构图文解析之:二叉堆详解及C++模板实现
- 数据结构图文解析之:栈的简介及C++模板实现
- 栈的简介及C++模板实现
- 用C++模板实现正则表达式
- C++队列实现和队列简介(不是循环队列)
- 使用C++模板实现不需要IDL的RPC【二】