堆排序算法是一種選擇排序,主要思想是選好一個非葉子節點子樹,然後用該子樹較大的孩子跟父節點比較,較大者跟父節點交換。如果交換後,孩子節點不滿足大根堆排序,則交換依次後,用交換的孩子作爲根節點,對該孩子進行大根堆排序,直到所有孩子節點全部滿足大根堆排序,然後才繼續往上一層節點繼續比較排序;
下圖是對大根堆排序原理圖文動態講解,引用這篇博主(https://blog.csdn.net/LoveHYZH/article/details/86748132#422__165)的圖。
一、大根堆排序原理
大根堆排序的原理如下
1.1先從最後一個非葉子節點的子樹開始,從該子節點數依次從右到左,然後從下到上進行大根堆排序。
1.2先寫最後一個非葉子節點的子樹大根堆第一遍排序,然後再排列子樹的孩紙也要進行大根堆排序;
1.3最後,用一個for循環,依次找到最後一個非葉子節點的子樹的根節點,從左到右,從下到上,循環對子樹進行大根堆排序。
二、代碼如下
void buildMaxHeap(int arr[],int size)
{
int parent=size/2-1;//最後一個非葉子節點所在子樹的根節點開始構建最大堆
for(int parentDyn=parent;parentDyn>=0;parentDyn--)
{
int parentTmp=parentDyn;//子樹父親,也即是該子樹的根節點,對該子樹進行大根堆排序
int child=2*parentTmp+1;//左孩子
while (child<=size-1)//左孩子下標超過數組最大長度,也即是多出了一層二叉樹;
{//該循環有兩個作用:1.對根節點樹第一層進行大根堆排序;2.對根節點的交換位置的子樹進行多層大根堆排序
//1.對根節點樹進行大根堆排序;
if((child+1<=size-1)&&(arr[child]<arr[child+1]))//比較子樹左右孩大小,選擇較大者下標,與父節點進行比較;且下標要在數組指定長度內
child++; //右孩子
if(arr[parentTmp]<arr[child])//比較該子樹的父節點和較大的孩子節點
{
std::swap(arr[parentTmp],arr[child]);
//2.對根節點的交換位置的子樹進行大根堆排序序
parentTmp=child;
child=2*parentTmp+1;//左孩子
}
else
{
break;
}
}
}
}
void maxHeapSort(int arr[],int size)
{
for(int length=size;length>1;length--)
{
buildMaxHeap(arr,length);
std::swap(arr[0],arr[length-1]);//把排序好的大根堆的根節點,依次跟數組最後一個數交換;
}
}
//調用用法如下
void Widget::on_pushButton_clicked()
{
int arr[] = {79,66,43,83,30,87,38,55,91,72,49,9};
maxHeapSort(arr,12);
for(quint32 i=0;i<12;i++)
qDebug("%d ",arr[i]);
}
輸出結果:
參考內容:
https://www.jianshu.com/p/21bef3fc3030(參考:堆排序原理講解,推薦!!!)
https://blog.csdn.net/LoveHYZH/article/details/86748132#422__165(參考:堆排序C++代碼實現,推薦!!!)
https://blog.csdn.net/WGH100817/article/details/101721306#title-13(參考:堆排序原理講解)
https://jingyan.baidu.com/article/5225f26b057d5de6fa0908f3.html(參考:C++代碼實現)