堆排序

堆排序是另一种时间复杂度为O(nlogn)的排序算法,它的实现依赖于二叉堆,优点是就地排序,无需额外空间,最坏时间复杂度也是O(nlogn),缺点是不稳定。

理解了二叉堆,堆排序可谓水到渠成。仍以整型数组按从小到大排序为例,由于要求从小到大排,得用大根堆,步骤如下:

  1. 建立大根堆
  2. 从堆中弹出最大元素,将它与下标最大的乱序元素交换
  3. 因弹出堆顶元素对堆做调整
  4. 反复执行2~3步骤,直到堆空为止
void SiftDown(int *a, int size, int idx) {
    int i, j;
    for (i = idx; (j = 2 * i + 1) < size; i = j) {
        if (j + 1 < size && a[j+1] > a[j])
            j += 1;
        if (a[j] <= a[i])
            break;
        swap(&a[i], &a[j]);
    }
}
void Heapify(int *a, int size) {
    int i;
    for (i = (size - 1) / 2; i >= 0; i--)
        SiftDown(a, size, i);
}
void HeapSort(int *a, int size) {
    int i;
    Heapify(a, size);
    for (i = size - 1; i > 0; i--) {
        swap(&a[0], &a[i]);
        SiftDown(a, i, 0);
    }
}

由于这里数组下标是从0开始的,需注意:

  • 根节点下标为0
  • 左子节点下标为2k+1,右子节点下标为2k+2
  • 有子节点的最大下标为(size-1)/2
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容