堆–c++实现
堆的定义
一颗大根树(小跟树) 是这样一棵树,其中每个节点的值都大于(小于)或等于其子节点(如果有子节点的话)的值。
大根树:
小根数:
在以上树图中虽然都是二叉树,但在大根树和小根树中,这是不必要的,其节点的子节点个数可以任意。
一个大根堆(小根堆) 既是大根树(小跟树)也是完全二叉树。
完全二叉树:一棵深度为k的有n个结点的 二叉树 ,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与 满二叉树 中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
简而言之,完全二叉树是由满二叉树按照顺序删减节点得到的。
堆的应用
对于优先级队列如果使用链表描述,每次删除或者查找时都需要遍历全部链表元素去寻找优先级最高(最低)的元素,所需的实现复杂度是 O ( n ) O(n) O(n),而如果使用堆来实现优先级队列,每次查找和删除的时间复杂度是 O ( h e i g h t ) O(height) O(height), height为完全二叉树的高度,即所需时间复杂度为 O ( l o g n ) O(logn) O(logn)。
堆的描述
在Heap.h文件中声明了堆的原型。
因为堆是完全二叉树,所以数组描述是较为方便的。
此处使用了vector(动态数组),其详细使用方法见:vector用法
#include<vector>
template<class T>
class Heap {
private:
std::vector<T> heap;
int heapSize;
public:
Heap();
~Heap();
const T& top() const;
void push(const T& element);
void pop();
int size() const;
bool isEmpty() const;
};
堆的实现
#include "Heap.h"
template<class T>
Heap<T>::Heap() {
heap = std::vector<T>(10);
heapSize = 0;
}
template<class T>
Heap<T>::~Heap() {
}
template<class T>
const T& Heap<T>::top() const {
return heap[1];
}
template<class T>
void Heap<T>::push(const T &element) {
int current = ++heapSize;
if (heapSize == 1){
heap[1] = element;
return;
}
if (heap[current/2] > element){
heap[current] = element;
return;
}
while (current != 1&&heap[current/2] < element){ //当插入的元素位置不是根节点时,让它与自己的双亲节点比较
heap[current] = heap[current/2]; //如果双亲节点小于此元素,则交换。
heap[current/2] = element;
current /= 2;
}
}
template<class T>
void Heap<T>::pop() {
int i = 1;
heapSize--;
while (2 * i < heapSize){
if (heap[2 * i] > heap[2*i +1]){
heap[i] = heap[2 * i];
i = 2*i;
} else{
heap[i] = heap[2*i +1];
i = 2*i +1;
}
}
}
template<class T>
int Heap<T>::size() const {
return heapSize;
}
template<class T>
bool Heap<T>::isEmpty() const {
return heapSize == 0;
}
测试程序:
#include <iostream>
using namespace std;
int main(){
Heap<int> heap;
heap.push(12);
heap.push(23);
heap.push(14);
heap.push(2);
heap.push(4);
heap.push(59);
cout << "top = " << heap.top()<<endl;
cout << "size = " << heap.size() << endl;
heap.pop();
cout << "after pop, top = " << heap.top() << endl;
cout << "now size = " << heap.size();
return 0;
}
59 | 12 | 23 | 2 | 4 | 14 |
---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 |
数组描述如上表
二叉树描述如上图
测试结果:
top = 59
size = 6
after pop, top = 23
now size = 5