堆排序算法是一种选择排序,主要思想是选好一个非叶子节点子树,然后用该子树较大的孩子跟父节点比较,较大者跟父节点交换。如果交换后,孩子节点不满足大根堆排序,则交换依次后,用交换的孩子作为根节点,对该孩子进行大根堆排序,直到所有孩子节点全部满足大根堆排序,然后才继续往上一层节点继续比较排序;
下图是对大根堆排序原理图文动态讲解,引用这篇博主(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++代码实现)