一步一步学算法-堆排序

来源:互联网 发布:windows虚拟内存转移 编辑:程序博客网 时间:2024/05/23 23:02

二叉堆有两种:最大堆和最小堆。在最大堆中,最大堆的特性是指除了根以外的每个节点 i,有

A[PARENT(i)] >= A[i]

即某个节点的值至多是和其父节点的值一样大。这样,堆中的最大元素就存放在根节点中;并且,在以某一节点为根的子树中,各节点的值都不大于该子树根节点的值。最小堆则相反。这里以最大堆为例子。

实现堆排序分为三个部分,即三个函数:
- 保持堆的性质
- 建堆
- 堆排序算法

保持堆的性质

void Algorithm::maxHeapify(int a[], int length, int i){    int largest = i;    int left = 2 * i + 1; // left child    int right = 2 * i + 2; // right child    // compare with two child node and get largest node    if (left < length && a[left] > a[largest])    {        largest = left;    }    if (right < length && a[right] > a[largest])    {        largest = right;    }    if (largest != i)    {        int tmp = a[largest];        a[largest] = a[i];        a[i] = tmp;        maxHeapify(a, length, largest);    }}

该函数的作用是调整二叉树,使得以 i 为根节点的子树成为最大堆。

建堆

void Algorithm::buildMaxHeap(int a[], int length){    for (int i = (length - 2) / 2; i >= 0; --i)    {        maxHeapify(a, length, i);    }}

建堆的过程就是把数组 a 自底向上用 maxHeapify 函数变成一个最大堆。

堆排序算法

void Algorithm::heapSort(int a[], int length){    buildMaxHeap(a, length);    for (int i = length - 1; i >= 1; --i)    {        // 交换a[0]和a[i]        int tmp = a[i];        a[i] = a[0];        a[0] = tmp;        maxHeapify(a, i, 0);    }}

通过堆的性质可以知道最大堆的根节点值一定最大,所以数组中最大元素在根 a[0],通过把它与 a[n] 互换来达到最终的位置。由于互换后 a[0] 的值被改变了,违背了最大堆的性质,这时调用 maxHeapify 调整数组前 n-1 个元素可以保持这一性质。

测试结果:

0 0