1. 原理

最大/最小堆的堆顶元素是整个数据集的最大/最小值。利用这个性质,可以首先取得堆顶元素作为有序序列的第一个元素,然后把剩余元素调整成堆,再取出堆顶元素放到有序序列的第二个位置,以此类推,就可以得到一个有序序列。

根据这种介绍可以看出得到升序序列需要最大堆,降序序列需要最小堆。

2. 代码

typedef int(*Compare)(int x, int y);  // 通过回调函数直接控制排出的是升序还是降序

// call back
int Greater(int x, int y);
int Less(int x, int y);

void AdjustDown(int* arr, int size, int root, Compare compare) {
    int parent = root;
    int child = parent * 2 + 1;

    while (child < size) {
        if (child + 1 < size && compare(arr[child + 1], arr[child])) {
            child++;
        }

        if (compare(arr[child], arr[parent])) {
            Swap(&arr[child], &arr[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else {
            break;
        }
    }
}

void HeapSort(int* arr, int size, Compare compare) {
    if (size == 1) {
        return;
    }

    // 1. 建堆
    int index = (size - 1) / 2;
    while (index >= 0) {
        // 向下调整
        AdjustDown(arr, size, index, compare);
        index--;
    }

    // 2. 排序
    int end = size - 1;
    Swap(&arr[0], &arr[end--]);
    while (end) {
        // 向下调整
        AdjustDown(arr, end + 1, 0, compare);

        Swap(&arr[0], &arr[end--]);
    }
}
Last modification:November 28th, 2021 at 09:36 pm