二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足二个特性:
1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。
下面这段代码实现了数组实现一个最小堆的过程,包括构造堆,堆的插入、删除操作。具体细节会在注释中给出解释。
MinHeap.hpp
#pragma once #include<iostream> using namespace std; #include<vector> template<class T> class MinHeap{ public: MinHeap() {} MinHeap(const T* array, size_t size){ //将数组元素逐个插入到vector里 for (int i = 0; i < size; i++){ _array.push_back(array[i]); } //计算最后一个非叶子结点,并从这个结点开始调整 int begin = _array.size() / 2 - 1; for (; begin >= 0; begin--){ _AdjustDown(begin); } } MinHeap(vector<T>& array){ //将数组元素逐个插入到vector里 for (int i = 0; i < array.size(); i++){ _array.push_back(array[i]); } //计算最后一个非叶子结点,并从这个结点开始调整 int begin = _array.size() / 2 - 1; for (; begin >= 0; begin--){ _AdjustDown(begin); } } void Insert(const T& x){ _array.push_back(x); //插入结点 _AdjustUp(_array.size() - 1); //重新调整 } void RemoveHeapTop(){ //检查堆中是否还有元素 if (_array.size() == 0){ cout << "empty array" << endl; return; } //将最后一个结点的值给第一个结点,并删除最后一个结点 _array[0] = _array[_array.size() -1]; _array.pop_back(); _AdjustDown(0); //重新调整 } protected: void _AdjustDown(int root){ //计算结点的左右节点的下标 int left = root * 2 + 1; int right = left + 1; //检查root是否为叶子结点,是否产生越界 while (left < _array.size()){ //找出左右结点中的最小值,并与父结点交换 int min = left; if (right < _array.size() && _array[left] > _array[right]) min = right; if (_array[min] < _array[root]){ swap(_array[root], _array[min]); //继续调整直到满足小堆条件 root = min; left = root * 2 + 1; right = left + 1; } else break; } } void _AdjustUp(int child){ //计算插入结点的父结点 int root = (child - 1) / 2; //一直向上调整直到根结点的值小于左右结点 while (root > 0){ if (_array[child] < _array[root]){ swap(_array[child], _array[root]); child = root; root = (child - 1) / 2; } else break; } if (_array[child] < _array[root] && root == 0) swap(_array[child], _array[root]); } private: vector<T> _array; };
这里的向上调整和向下调整函数可以实现对堆的处理。向上调整用于插入之后的排序,要注意循环条件和边界值的部分。
这里的测试用例二实现了对一个vector类对象的构造
main.cpp
#include<iostream> using namespace std; #include"MinHeap.hpp" #include<vector> void test1(){ int arr[10] = { 10, 16, 18, 11, 12, 13, 15, 17, 14, 19 }; int size = sizeof(arr) / sizeof(arr[0]); MinHeap<int> hp1(arr,size); hp1.Insert(9); hp1.Insert(7); hp1.RemoveHeapTop(); hp1.RemoveHeapTop(); hp1.RemoveHeapTop(); } void test2(){ int array[10] = { 10, 16, 18, 11, 12, 13, 15, 17, 14, 19 }; vector<int> arr; for (int i = 0; i < 10; i++){ arr.push_back(array[i]); } MinHeap<int> hp2(arr); hp2.Insert(9); hp2.Insert(7); hp2.RemoveHeapTop(); hp2.RemoveHeapTop(); hp2.RemoveHeapTop(); } int main(){ test1(); test2(); return 0; }
本文出自 “moLova” 博客,请务必保留此出处http://molova.blog.51cto.com/10594266/1716753
原文:http://molova.blog.51cto.com/10594266/1716753