本文是轉載文章,文章的來源:csdn博客
博主:帶魚兄
文章:堆排序詳解
博文地址:https://blog.csdn.net/daiyudong2020/article/details/52529791
基本概念:
要了解堆排序,首先要了解什麼是堆,
要了解堆,還要先了解什麼是完全二叉樹。
一、什麼是完全二叉樹?
完全二叉樹(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[]={7,4,2,9,8,5},首先將數組視爲一個完全二叉樹,對其進行轉換成一個堆,構造初始堆是對所有的非葉節點都進行調整,從最後一個非葉節點開始調整,使其滿足堆的特性。
第一步,將數組視爲一個完全二叉樹:
第二步,將完全二叉樹轉換成一個堆:
最後得到一個最大堆:
四、如何使用堆進行排序?
基於以上堆相關的操作,我們可以很容易的定義堆排序。例如,假設我們已經讀入一系列數據並創建了一個堆,一個最直觀的算法就是反覆的調用del_max()函數,因爲該函數總是能夠返回堆中最大的值,然後把它從堆中刪除,從而對這一系列返回值的輸出就得到了該序列的降序排列。所以,堆排序,最重要的兩個操作就是構造初始堆和調整堆。
堆排序的過程是:
(1)建立一個堆H[0..n-1]。
(2)把堆首(最大值)和堆尾互換。
(3)把堆的尺寸縮小1,然後調整堆,目的構成新的堆。
(4)重複步驟2,直到堆的尺寸爲1。
平均時間複雜度O(nlogn)
動態圖:
下面展示如何將一個數組a[]={7,4,2,9,8,5}構建成堆進行排序:
第一步:構建初始堆:
第二步,開始排序,灰色表示被移除的堆尾(已排好序):
五、簡單例子
源碼:
#include <stdio.h>
/* 交換元素 */
void swap(int* a, int* b) {
int temp = *b;
*b = *a;
*a = temp;
}
/* 調整堆 */
void max_heapify(int arr[], int start, int end) {
//建立父節點下標和子節點下標
int dad = start;
int son = dad * 2 + 1;
while (son <= end) { //若子節點下標在範圍內才做比較
if (son + 1 <= end && arr[son] < arr[son + 1]) //先比較兩個子節點大小,選擇最大的
son++;
if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數
return;
else { //否則交換父子內容再繼續子節點和孫節點比較
swap(&arr[dad], &arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
/* 堆排序 */
void heap_sort(int arr[], int len) {
int i;
//初始化堆,i從最後一個父節點開始調整
for (i = len / 2 - 1; i >= 0; i--)
max_heapify(arr, i, len - 1);
//先將第一個元素和已排好元素前一位做交換,再從新調整,直到排序完畢
for (i = len - 1; i > 0; i--) {
swap(&arr[0], &arr[i]);
max_heapify(arr, 0, i - 1);
}
}
int main() {
int arr[] = {7, 4, 2, 9, 8, 5};
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;
}
編譯運行:
原文出自:http://blog.csdn.net/daiyudong2020/article/details/52529791
End;