定义
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
应用
排序 :堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序
优先队列:(个人很喜欢用,简单方便的sql)
priority_queue<int, vector<int>, greater<int> > q;
误区
根据定义,大根堆的根为最大元素也就是堆顶,那为什么要把大根堆对应升序呢?
调整的难易程度
前提 :作为一个堆结构,在输出或者输入数据以后为了维护原本的堆结构就要调整
排升序:使用大堆我们每次向下调整都可以得到剩余数据的最大值,即堆顶元。然后放到最后,使用分治的思想,当交换到最后一个结点时,数组已经排好序了。
假设排降序首先使用堆排序主要是用堆顶元素,如果使用大根堆排降序,此时堆顶的元素是最大的,当我们取出堆顶元素时,此时大根堆的性质就变了,那么下次就难以找到第二大元素,要重新建堆。
代码
void adjust_heap(int* a, int node, int size)
{
int left = 2*node + 1;
int right = 2*node + 2;
int max = node;
if( left < size && a[left] > a[max])
max = left;
if( right < size && a[right] > a[max])
max = right;
if(max != node)
{
swap( a[max], a[node]);
adjust_heap(a, max, size);
}
}
void heap_sort(int* a, int len)
{
for(int i = len/2 -1; i >= 0; --i)
adjust_heap(a, i, len);
for(int i = len - 1; i >= 0; i--)
{
swap(a[0], a[i]); // 将当前最大的放置到数组末尾
adjust_heap(a, 0 , i); // 将未完成排序的部分继续进行堆排序
}
}