堆的具体实现

来源:互联网 发布:照片摇奖软件 编辑:程序博客网 时间:2024/05/16 04:49

一、定义:

堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构。(是静态结构)

二、堆结构的二叉树存储结构:

最大堆:每个父节点的都大于孩子节点。
最小堆:每个父节点的都小于孩子节点。

三、大根堆和小根堆

1.大根堆:

函数声明如下:

template<class T>class Heap{public:Heap();Heap(const T* a, size_t size);Heap(vector<T> & a);//有动态顺序表构造,布斯和有数组构造,外面顺序表会被交换掉void Push(const T& x);void Pop();T& Top();size_t Size();bool Empty();protected:void _AdjustDown(size_t parent);void _AdjustUp(int child);protected:vector<T> _a;};

具体实现如下:

template<class T>Heap<T>::Heap(){}template<class T>Heap<T>::Heap(const T* a, size_t size){_a.reserve(size);for (size_t i = 0; i < size; ++i){_a.push_back(a[i]);}//建堆for (int i = (_a.size() - 2) / 2; i >= 0; --i){_AdjustDown(i);}}template<class T>Heap<T>::Heap(vector<T> & a){_a.swap(a);for (int i = (_a.size() - 2) / 2; i >= 0; --i){_AdjustDown(i);}}template<class T>void Heap<T>::Push(const T& x){_a.push_back(x);_AdjustUp(_a.size() - 1);}template<class T>void Heap<T>::Pop(){size_t size = _a.size();assert(size > 0);std::swap(_a[0], _a[size - 1]);_a.pop_back();_AdjustDown(0);}template<class T>T& Heap<T>::Top(){assert(_a.empty());return _a[0];}template<class T>size_t Heap<T>::Size(){return _a.size();}template<class T>bool Heap<T>::Empty(){return _a.size() == 0;}//下调template<class T>void  Heap<T>::_AdjustDown(size_t parent){size_t child = parent * 2 + 1;while (child < _a.size()){//选出左右孩子中最小的,有可能节点不存在if ((child + 1  < _a.size()) && (_a[child] < _a[child + 1])){++child;}if (_a[parent] < _a[child]){std::swap(_a[parent], _a[child]);parent = child;child = 2 * parent + 1;}else{break;}}}//上调template<class T>void Heap<T>::_AdjustUp(int child){int parent = (child - 1) / 2;while (child>0){if (_a[child] > _a[parent]){std::swap(_a[child], _a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}

2、小根堆

小根堆与大根堆的实现大体思路相同,主要是上调和下调的判断条件不相同而已,那么就可以使用仿函数在一份代码里面即实现大根堆又实现小根堆

(1)仿函数

不是函数,而是一个类,但可以像函数一样使用

例子:

比较两个数的大小

代码如下:

template<class T>struct Less{bool operator()(const T& l, const T& r){return l < r;}};template<class T>struct Greater{bool operator()(const T& l, const T& r){return l > r;}};

测试用例:

void TestFuner(){Less<int> less;cout << less(1, 2) << endl;//以为是函数其实是对象,去掉运算符重载}

c++用模版实现这种功能,其实C语言的函数指针可以实现

(2)小根堆的具体实现

代码如下:

template<class T>struct Less{bool operator()(const T& l, const T& r){return l < r;}};template<class T>struct Greater{bool operator()(const T& l, const T& r){return l > r;}};template<class T,template<class> class Compare = Less>class Heap{public:Heap(){}Heap(const T* a, size_t size){_a.reserve(size);for (size_t i = 0; i < size; ++i){_a.push_back(a[i]);}//建堆for (int i = (_a.size() - 2) / 2; i >= 0; --i){_AdjustDown(i);}}//外面顺序表会被交换掉Heap(vector<T> & a){_a.swap(a);for (int i = (_a.size() - 2) / 2; i >= 0; --i){_AdjustDown(i);}}void Push(const T& x){_a.push_back(x);_AdjustUp(_a.size() - 1);}void Pop(){size_t size = _a.size();assert(size > 0);std::swap(_a[0], _a[size - 1]);_a.pop_back();_AdjustDown(0);}T& Top(){assert(_a.empty());return _a[0];}protected:void _AdjustDown(size_t parent){size_t child = parent * 2 + 1;while (child < _a.size()){Compare<T> com;//选出左右孩子中最小的,有可能节点不存在if (child+1  < _a.size() &&com( _a[child] , _a[child + 1])){++child;}if (com(_a[parent] , _a[child])){std::swap(_a[parent], _a[child]);parent = child;child = 2 * parent + 1;}else{break;}}}void _AdjustUp(int child){int parent = (child - 1) / 2;while (child>0){Compare<T> com;//比较关系的对象if (com(_a[child] , _a[parent])){std::swap(_a[child], _a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}protected:vector<T> _a;};
测试用例:

void Test(){int a[] = { 10, 11, 13, 12, 16, 18, 15, 17, 14, 19 };Heap<int,Greater> hp1(a, sizeof(a) / sizeof(int));hp1.Push(20);cout << endl;}


0 0
原创粉丝点击