基本概念:
要了解堆排序,首先要了解什麼是堆,
要了解堆,還要先了解什麼是完全二叉樹。
一、什麼是完全二叉樹?
完全二叉樹(complete binary tree)有嚴格的形狀要求:從根節點起每一層從左到右填充。一棵高度為d的完全二叉樹除了d-1層以外,每一層都是滿的。底層葉節點集中在左邊的若干位置上。完全二叉樹如下圖:
二、什麼是堆?
堆實際上是一棵完全二叉樹,其任何一非葉節點滿足性質:
a)任何一非葉節點的關鍵字不大於其左右孩子節點的關鍵字,稱之為最小堆。
b)任何一非葉節點的關鍵字不小於其左右孩子節點的關鍵字,稱之為最大堆。
由上述性質可知:
a)最大堆的堆頂的關鍵字是所有關鍵字中最大的。
b)最小堆的堆頂的關鍵字是所有關鍵字中最小的。
通常堆是通過一維陣列來實現的,在起始位置為0的情形中:
父節點i的左子節點在位置(2*i+1);
父節點i的右子節點在位置(2*i+2);
子節點i的父節點在位置floor((i-1)/2);
乙個最大堆如圖:
三、完全二叉樹怎麼演變成乙個堆?
給定乙個整形陣列a=,首先將陣列視為乙個完全二叉樹,對其進行轉換成乙個堆,構造初始堆是對所有的非葉節點都進行調整,從最後乙個非葉節點開始調整,使其滿足堆的特性。
第一步,將陣列視為乙個完全二叉樹:
第二步,將完全二叉樹轉換成乙個堆:
最後得到乙個最大堆:
四、如何使用堆進行排序?
基於以上堆相關的操作,我們可以很容易的定義堆排序。例如,假設我們已經讀入一系列資料並建立了乙個堆,乙個最直觀的演算法就是反覆的呼叫del_max()函式,因為該函式總是能夠返回堆中最大的值,然後把它從堆中刪除,從而對這一系列返回值的輸出就得到了該序列的降序排列。所以,堆排序,最重要的兩個操作就是構造初始堆和調整堆
。堆排序的過程是:
(1)建立乙個堆h[0..n-1]。
(2)把堆首(最大值)和堆尾互換。
(3)把堆的尺寸縮小1,然後調整堆,目的構成新的堆。
(4)重複步驟2,直到堆的尺寸為1。
平均時間複雜度o(nlogn)
動態圖:
下面展示如何將乙個陣列a=構建成堆進行排序:
第一步:構建初始堆:
第二步,開始排序,灰色表示被移除的堆尾(已排好序):
五、簡單例子
原始碼:
#include /* 交換元素 */
void swap(int* a, int* b)
/* 調整堆 */
void max_heapify(int arr, int start, int end)
}}/* 堆排序 */
void heap_sort(int arr, int len)
}int main() ;
int len = sizeof(arr) / sizeof(int);
/* sort */
heap_sort(arr, len);
/* print */
int i;
for (i = 0; i < len; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
編譯執行:
原文出自:
end;
排序詳解 堆排序
堆排序 heapsort 是指利用堆積樹 堆 這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即a parent i a i 在陣列的非降序排序中,需要使用的就是大根...
堆排序詳解
一 堆的定義 堆的定義如下 n個關鍵字序列l n 成為堆,當且僅當該序列滿足 l i l 2i 且l i l 2i 1 或者 l i l 2i 且l i l 2i 1 其中i屬於 1,n 2 滿足第 種情況的堆稱為小根堆 小頂堆 滿足第 種情況的堆稱為大根堆 大頂堆 在大根堆中,最大元素存放在根結點...
堆排序詳解
public class heapsort 此時已經完成了最大堆的構建,下面進行排序。for int i len 1 i 0 i 維護最大堆,保證父節點大於等於子節點 public static void maxheapify int a,int index,int len if rightchil...