堆排序(Heap Sort),只需要一个记录大小的辅助空间,每个待排序的记录仅占有一个存储空间。堆的定义如下:n个元素的序列{k1, k2, … , kn}当且仅当满足下关系时,称之为堆。
Ki <= K2i && Ki <= K2i+1 或 Ki >= K2i && Ki >= K2i+1,(i = 1, 2, … , n/2」)。若将和此序列对应的一维数组看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。理解:若在输出堆顶的最小值之后,使得剩余的n – 1个元素的序列重又建成一个堆,则得到n个元素中的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。时间复杂度为O(nlogn)。
由此,实现堆排序需要解决两个问题:(1)如何由一个无序序列建成一个堆?(2)如何在输出堆顶元素之后,调整剩余元素成为一个新的堆?
// 堆排序
void CSelectionSort::HeapSort(void)
{
const int count = 9, length = count -1;
int L[count] = {0, 49, 38, 65, 97, 76, 13, 27, 49};
int i = 0;
for (i = length / 2; i > 0; -- i)
HeapAdjust(L, i, length);
for (i = length; i > 1; -- i)
{
int temp = L[1];
L[1] = L[i];
L[i] = temp;
HeapAdjust(L, 1, i - 1);
}
//打印排序结果。
for (int i = 0; i < count; ++ i)
{
cout << L[i] << "\t";
}
cout << endl;
}
// 堆排序之堆调整
void CSelectionSort::HeapAdjust(int H[], int s, int m)
{
int rc = H[s];
for (int j = 2 * s; j <= m; j *= 2)
{
if (j < m && H[j] < H[j + 1])
++ j;
if (rc >= H[j])
break;
H[s] = H[j];
s = j;
}
H[s] = rc;
}