堆排序詳解

2021-08-19 14:51:57 字數 2390 閱讀 7140

基本概念:

要了解堆排序,首先要了解什麼是堆,

要了解堆,還要先了解什麼是完全二叉樹。

一、什麼是完全二叉樹?

完全二叉樹(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...