聪明人做事通常以结果为导向,故先说一下堆排序的应用场景:用于处理优先级队列或类似于优先级队列的相关问题,比如要返回最大或最小元素,或只有有限插入要求等。
堆(heap),一种数据结构,逻辑上是一棵完全二叉树,存储上是一个数组对象 (二叉堆),满足的条件是:所有非叶子结点的值均不大于或均不小于其左、右孩子结点的值。
堆排序的思想如下:利用heap这种数据结构(所有非叶子结点的值均不大于或均不小于其左、右孩子结点的值),使在排序中比较的次数明显减少。简单理解就是A为父节点,B,C为A的左右子节点,把A,B,C三个节点中数值最大(或最小)的放在父节点(A),然后再递归检查较大(或较小)值的子节点(比如B与其子节点B1,B2,这三者的比较)。
堆排序的时间复杂度与快速排序的时间复杂度一样,为O(nlogn),它是一种非稳定排序(有相等元素时,算法对这些元素的处理方式不止一种),原地排序(空间复杂度为O(1));
具体代码如下: (建立最大堆,及根节点数值最大)
void Heapfy(int A[],int iIndex,int iMax) //建立最大堆
{
int iLeft = iIndex * 2 +1; //节点iIndex 的左子节点;
int iRight = iLeft + 1; //节点iIndex 的右子节点;
int iLargest = iIndex;
if(iLeft < iMax && A[iLeft] > A[iLargest)
{
iLargest = iLeft;
}
if(iRight < iMax && A[iRight] > A[iLargest])
{
iLargest = iRight;
}
if(iLargest != iIndex )
{
//将较大的节点值交换到其所在节点的父节点上
int iTemp = A[iLargest];
A[iLargest] = A[iIndex];
A[iIndex] = iTemp;
Heapfy(A,iLargest,iMax); //递归遍历子节点
}
}
void BuildHeap(int A[],int iSize)
{
int iLenght = iSize; //数组长度
for(int i = iLenght/2 -1; i >= 0; --i)
{
Heapfy(A,i,iLenght); //建立最大堆
}
for(int j = iLenght - 1; j >= 1; --j)
{
int iTemp = A[0]; //将当前堆的根节点交换到堆尾的指定位置
A[0] = A[j];
A[j] = iTemp;
Heapfy(A, 0, j);
}
}