欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

堆排序之堆的概念—插入、删除、建堆

程序员文章站 2024-02-14 09:50:16
...

内容会持续更新,有错误的地方欢迎指正,谢谢!

堆的性质

  1. 性质:完全二叉树 或 近似完全二叉树(不是满二叉树的完全二叉树)。
  2. 分类:最大堆:父节点的值不小于子节点;最小堆:父节点的值不大于子节点。
  3. 左右子节点:没有大小的顺序。
  4. 堆的存储:
    一般都用数组来存储堆。下标为i的节点的父节点的下标为(i–1)/2。根节点的左右子节点下标分别为 2∗i+1 和 2∗i+2。例如:下标为0的节点左右子节点的下标分别为1和2。
  5. 堆的操作:插入、删除、建堆。

最小堆的图:
堆排序之堆的概念—插入、删除、建堆

插入

原理:新元素必须插入到二叉树的末尾(即堆尾)。如果该数组构成的二叉树不满足堆的性质,则需要重新排列元素—“上浮”操作。

最小堆的插入操作图:
堆排序之堆的概念—插入、删除、建堆

最大堆的插入操作的代码:

//非常建议各位看官根据对原理的理解,写出自己的代码,切忌看我的代码去理解算法,否则很快就会忘记!
void MaxHeapFixUp(int* array, int index) 
{
    //index为插入的节点的下标,则其父节点为(index-1)/2。
    int indexFather = (index - 1) / 2;
    int temp = 0;
    while(index!=0)
    {
        if (array[indexFather] < array[index])
        {
            temp = array[index];
            array[index] = array[indexFather];
            array[indexFather] = temp;
        }
        else
            break;
        index = indexFather;
        indexFather = (index - 1) / 2;
    }
}

删除

原理:删除操作必须删除该二叉树的根节点(即堆顶)。堆中最后一个元素用来补空,再重新排列元素—“下沉”操作。

最小堆的删除操作图:
堆排序之堆的概念—插入、删除、建堆

删除操作的代码:

//非常建议各位看官根据对原理的理解,写出自己的代码,切忌看我的代码去理解算法,否则很快就会忘记!
void MaxHeapFixDown(int* array, int length, int index)
{
    ///index为待下沉的父节点的下标,其子节点为2*index+1和2*index+2。
    //本代码段只包含对根节点的下沉部分。
    int temp = array[index];
    int indexOfSon = 2 * index + 1;
    while (indexOfSon < length) 
    {
        if (indexOfSon + 1 < length&&array[indexOfSon + 1] > array[indexOfSon])
            ++indexOfSon;
        if (array[indexOfSon] < temp)
            break;
        array[index] = array[indexOfSon];
        index = indexOfSon;
        indexOfSon = 2 * index + 1;
    }
    array[index] = temp;
}

建堆(堆调整)

最小堆的初始图:
堆排序之堆的概念—插入、删除、建堆

原理:很明显,对叶子结点来说,可以认为它已经是一个合法的堆了,即 20,60, 65,4, 49 都分别是一个合法的堆。只要从 a[4]=50 开始向下进行堆调整就可以了。然后再对 a[3]=30,a[2] = 17,a[1] = 12,a[0] = 9 分别作一次向下堆调整就可以了。

下面展示了建最小堆的步骤:
堆排序之堆的概念—插入、删除、建堆

建最大堆的代码:

void MakeMaxHeap(int* array, int length)
{
    //length/2-1恒等于最后一个根节点的下标。
    for (int i = length / 2 - 1; i >= 0; --i) 
    {
        //调用删除(下沉)操作
        MaxHeapFixDown(array, 10, i);
    }
}

堆排序的实现

请查看我的另一篇博客,里面有详细地介绍:树形选择排序—堆排序