实现如下:
int getParent(int c);
int getLeft(int p);
int getRight(int p);
void swap(int *p1, int *p2);
void heap_sort(int *source, int length);
void max_heapify(int *source, int length, int loc);
void build_max_heap(int *source, int length);
void heap_sort_iteration(int *source, int length);
void max_heapify_iteration(int *source, int length, int loc);
void build_max_heap_iteration(int *source, int length);
int getParent(int c) {
return (c - 1) / 2;
}
int getLeft(int p) {
return p * 2 + 1;
}
int getRight(int p) {
return p * 2 + 2;
}
void swap(int *p1, int *p2) {
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void max_heapify(int *source, int length, int loc) {
int l = getLeft(loc);
int r = getRight(loc);
int max = loc;
if (l < length && source[l] > source[max])
max = l;
if (r < length && source[r] > source[max])
max = r;
if (max == loc)
return;
swap(source + max, source + loc);
max_heapify(source, length, max);
}
void build_max_heap(int *source, int length) {
for (int i = getParent(length - 1); i >= 0; --i) {
max_heapify(source, length, i);
}
}
void heap_sort(int *source, int length) {
build_max_heap(source, length);
for (int i = length - 1; i > 0; --i) {
swap(source, source + i);
max_heapify(source, i, 0);
}
}
void max_heapify_iteration(int *source, int length, int loc) {
int l, r;
int max = loc;
while (loc < length) {
l = getLeft(loc);
r = getRight(loc);
if (l < length && source[l] > source[max])
max = l;
if (r < length && source[r] > source[max])
max = r;
if (max == loc)
return;
swap(source + max, source + loc);
loc = max;
}
}
void build_max_heap_iteration(int *source, int length) {
for (int i = getParent(length - 1); i >= 0; --i) {
max_heapify_iteration(source, length, i);
}
}
void heap_sort_iteration(int *source, int length) {
build_max_heap(source, length);
for (int i = length - 1; i > 0; --i) {
swap(source, source + i);
max_heapify_iteration(source, i, 0);
}
}
堆排序是不稳定原地的排序。
该程序中使用的数组作为表示堆的数据结构,其计算左子女,右子女以及父节点的坐标的方式如parent,left_child,right_child所示。
max_heapify使其保持最大堆的性质,假设p节点左右两颗子树都是最大堆,max_heapify使p节点保持最大堆的性质,选取p节点的左右子女中最大的与p节点交换,然后递归的对交换后的节点继续进行max_heapify操作,直到到达叶子结点。max_heapify操作运行时间的渐近上界为 Ο(h) h为待操作节点的高度。
build_max_heap将一个数组建立为最大堆,从最后一个非叶子节点到根节点依次分别调用max_heapify函数即可。其操作时间的渐近确界为 Ο(n) 。
heap_sort函数对n个数进行堆排序,每次将最大堆的第一个元素和最后一个元素交换,得到最大的元素,将堆的元素个数减一后再对堆的根节点进行max_heapify操作,得到当前堆中最大元素,循环n-1次即可排序数组。其操作时间的渐近确界为 Ο(nlogn) 。
其上所有算法复杂度计算方法见算法导论第六章,涉及主定理不再赘述。