堆排序(Heap sort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。堆排序可以用到上一次的排序結果,所以不像其他一般的排序方法一樣,每次都要進行n-1次的比較,復雜度為O(nlogn)。
這里先說明以下幾個基本概念:
完全二叉樹:假設一個二叉樹有n層,那么如果第1到n-1層的每個節點都達到最大的個數:2,且第n層的排列是從左往右依次排開的,那么就稱其為完全二叉樹
堆:本身就是一個完全二叉樹,但是需要滿足一定條件,當二叉樹的每個節點都大於等於它的子節點的時候,稱為大頂堆,當二叉樹的每個節點都小於它的子節點的時候,稱為小頂堆,上圖即為小頂堆。
關鍵的性質:
將堆的內容填入一個一維數組,這樣通過下標就能計算出每個結點的父子節點,編號順序從0開始,從左往右,從上至下層次遍歷。a[10] = {2,8,5,10,9,12,7,14,15,13}
若一個結點的下標為k,那么它的父結點為(k-1)/2,其子節點為2k+1和2k+2
例:數字為10的節點的下標為3,父結點為1號:8,子節點為7號和8號:14,15
算法步驟:
1)利用給定數組創建一個堆H[0..n-1](我們這里使用最小堆),輸出堆頂元素
2)以最后一個元素代替堆頂,調整成堆,輸出堆頂元素
3)把堆的尺寸縮小1
4) 重復步驟2,直到堆的尺寸為1
實現代碼:
#include <iostream> #include <vector>
#include <algorithm>
#include <time.h> #include <Windows.h> using namespace std;//堆排序的核心是建堆,傳入參數為數組,根節點位置,數組長度 void Heap_build(int a[],int root,int length) { int lchild = root*2+1;//根節點的左子結點下標 if (lchild < length)//左子結點下標不能超出數組的長度 { int flag = lchild;//flag保存左右節點中最大值的下標 int rchild = lchild+1;//根節點的右子結點下標 if (rchild < length)//右子結點下標不能超出數組的長度(如果有的話) { if (a[rchild] > a[flag])//找出左右子結點中的最大值 { flag = rchild; } } if (a[root] < a[flag]) { //交換父結點和比父結點大的最大子節點 swap(a[root],a[flag]); //從此次最大子節點的那個位置開始遞歸建堆 Heap_build(a,flag,length); } } } void Heap_sort(int a[],int len) { for (int i = len/2; i >= 0; --i)//從最后一個非葉子節點的父結點開始建堆 { Heap_build(a,i,len); } for (int j = len-1; j > 0; --j)//j表示數組此時的長度,因為len長度已經建過了,從len-1開始 { swap(a[0],a[j]);//交換首尾元素,將最大值交換到數組的最后位置保存 Heap_build(a,0,j);//去除最后位置的元素重新建堆,此處j表示數組的長度,最后一個位置下標變為len-2 } } int main(int argc, char **argv) { clock_t Start_time = clock(); int a[10] = {12,45,748,12,56,3,89,4,48,2}; Heap_sort(a,10); for (size_t i = 0; i != 10; ++i) { cout<<a[i]<<" "; } clock_t End_time = clock(); cout<<endl; cout<<"Total running time is: "<<static_cast<double>(End_time-Start_time)/CLOCKS_PER_SEC*1000<<" ms"<<endl; cin.get(); return 0; }
建堆的過程,堆調整的過程,這些過程的時間復雜度,空間復雜度,以及如何應用在海量數據Top K問題中等等,都是需要重點掌握的。
復雜度分析:
最差時間復雜度O(n log n)
最優時間復雜度O(n log n)
平均時間復雜度O(n log n)
最差空間復雜度O(n)
注意:此排序方法不適用於個數少的序列,因為初始構建堆需要時間;
特點分析:不穩定算法(unstable sort)、In-place sort。
---------------------
轉載:
作者:MISAYAONE
來源:CSDN
原文:https://blog.csdn.net/misayaaaaa/article/details/65999854
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
有問題歡迎一起討論!
