定義
堆是具有以下性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱爲大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱爲小頂堆。如下圖:
應用
排序 :堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均爲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); // 將未完成排序的部分繼續進行堆排序
}
}