堆是一种优先队列的实现。堆是一颗完全二叉树,所谓完全二叉树就是除了最后一层以外,其他层都是满的,而且最后一层所缺的叶结点都在右边。
在完全二叉树中,节点的序列号有如下关系:
特性4:设完全二叉树中一元素的序号为i,1<=i<=n.则有以下关系:
当i=1时,节点为树的根。若i>1,则该元素父节点为i/2(向下取整)
当2*i>n时,该元素无左孩子。否则,其左孩子为2*i。
当2*i+1>n时,无右孩子。否则,右孩子为2*i+1。
可以用公式化描述的树来高效存储完全二叉树。
1.定义
最大树:每个节点的值都大于或等于其子节点(如果有的话)值得树。(最大树可以多于二叉)
最大堆:最大的完全二叉树
由于堆是完全的二叉树,因而可以利用它的这一特性方便的用数组实现堆。
2.最大堆的插入
插入时,从最后一个元素向根结点方向搜索,找到对应的位置插入。O(log2n)
3.最大堆的删除
删除根结点,然后将最后一个叶结点放入根结点,并向下搜索,找到对应位置插入。O(log2n)
4.最大堆的初始化
可以用n个数组元素初始化最大堆。初始化的过程可以分为n个插入操作,所需时间为O(nlogn)。或者用下面这种方式,时间为O(n)
从第一个具有孩子的节点开始(即节点 n),这个元素在数组中的位置为 i = [n / 2 ],如果以这个元素为根的子树已是最大堆,则此时不需调整,否则必须调整子树使之成为堆。随后,继续检查以 i-1, i-2等节点为根的子树,直到检查到整个二叉树的根节点(其位置为1)。
5.实现
类定义:
1 template<typename T> 2 class MaxHeap 3 { 4 public: 5 MaxHeap(int MaxHeapSize = 10); 6 ~MaxHeap() 7 { 8 if (heap!=NULL) 9 { 10 delete[] heap; 11 heap = NULL; 12 } 13 } 14 15 int Size() const{ return CurrentSize; } 16 T Max() 17 { 18 if (CurrentSize==0) 19 { 20 throw OutofBounds(); 21 } 22 23 return heap[1]; 24 } 25 26 MaxHeap<T>& Insert(const T& x); 27 MaxHeap<T>& DeleteMax(T& x); 28 void Initialize(T a[], int size, int ArraySize); 29 private: 30 int CurrentSize; 31 int MaxSize; 32 T* heap; 33 };