1、基本思想
将数组划分成无序区和有序区,利用大根堆或小根堆思想。
1)首先将无序区elem[0,n-1]建立大根堆,然后将堆首elem[0]与堆尾elem[n-1]交换,堆尾之后为有序区。
2)将新的无序区elem[0,n-2]调整为大根堆,然后将堆首elem[0]与堆尾elem[n-2]交换,堆尾进入有序区。
3)将新的无序区elem[0.n-3]调整为大根堆……重复操作,直到无序区只有一个元素为止,排序结束。
2、堆实质上是满足完全二叉树的性质的:树的任一非叶结点的数据均不大于(或不小于)其左右孩子(若存在)结点的数据。
大根堆:根结点的数据均不小于其左右孩子结点的数据。
小根堆:根结点的数据均不大于其左右孩子结点的数据。
3、堆排序是一种不稳定的排序。
时间复杂度O(nlogn)。空间复杂度O(1)。
4、代码
将elem[]数组按递增进行堆排序
void Heapify(int elem[], int node, int length)
{
//记录头结点
int tempElem = elem[node];
//左右孩子序号
int leftChild = 2*node+1;
int rightChild = 2*node+2;
while(leftChild < length)
{
rightChild = 2*node+2;
//判断是否存在右孩子,并且右孩子比左孩子大时,用右孩子与头结点比较
if((rightChild < length) && (elem[rightChild] > elem[leftChild]))
{
//将比结点大的孩子与结点交换
if(elem[rightChild] > tempElem)
{
elem[node] = elem[rightChild];
elem[rightChild] = tempElem;
node = rightChild;
}else
{
break;
}
}else
{
if(elem[leftChild] > tempElem)
{
elem[node] = elem[leftChild];
elem[leftChild] = tempElem;
node = leftChild;
}else
{
break;
}
}
tempElem = elem[node];
leftChild = 2*node+1;
}
}
void HeapSort(int elem[], int elemLen)
{
//建立大根堆,头节点的个数
for(int i = elemLen/2 - 1; i >= 0; i--)
{
Heapify(elem, i, elemLen);
}
int tempElem = 0;//交换数据的中间变量
for(int i = elemLen-1; i > 0; i--)
{
//将堆首与堆尾交换
tempElem = elem[i];
elem[i] = elem[0];
elem[0] = tempElem;
//重新调整交换后的无序区为大根堆
Heapify(elem, 0, i);
}
}