堆排序

本文深入探讨了堆这种特殊的数据结构,包括最大堆和最小堆的定义及建堆步骤。通过向下调整操作详细阐述了如何构建最大堆。此外,介绍了堆排序的基本思想和算法步骤,以及堆排序的时间复杂度和空间复杂度。堆排序是一种高效的排序算法,适用于大数据量的排序场景。
摘要由CSDN通过智能技术生成

1. 堆

1.1 堆
堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 堆总是一棵完全二叉树。

1.2 分类

  1. 最大堆:根结点最大的堆
  2. 最小堆:根结点最小的堆

1.3 建堆步骤

  1. 从最后一个非叶子节点开始(自下而上构建每一个子树),对每一个非叶子节点进行向下调整操作(最后一个节点的父节点 i=(end-1) / 2,其中end=n-1);
  2. i–,继续向前调整非叶子节点,直到调整完所有的非叶子节点,得到相应的最小堆或者最大堆。

向下调整操作步骤:

  1. 找出要调整节点的子节点中的最大值;
  2. 父子节点进行比较,若父节点>子节点,则进行交换操作。
  3. 将父节点更新为此时的子节点,继续循环1、2步骤;
  4. 直到更新完变动的子树结束。

1.4 建堆代码

void swap(int* a, int* b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

//1.向下调整(建最大堆)
void ShiftDown(int* arr, int n, int parent)
{
    //1.将左右子节点中较大的一个与父节点进行比较,若父节点小于他们两个中的较大值,则交换父子节点,更新父节点继续比较。
    int child = parent * 2 + 1;             //左孩子节点下标
    
    while (child < n)
    {
        if (child + 1 < n - 1 && arr[child + 1] > arr[child])
                child++;
        if (arr[child] > arr[parent])
        {
            swap(&arr[child], &arr[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}

//1.向下调整(建最大堆)——递归
void ShiftDown1(int* arr, int n, int parent)
{
    if (parent >= n)            //递归出口
    {
        return;
    }
    int child = parent * 2 + 1; //左孩子

    if (child + 1 < n && arr[child + 1] > arr[child])
        child++;
    if (child<n && arr[child]>arr[parent])
    {
        swap(&arr[child], &arr[parent]);
        ShiftDown1(arr, n, child);
    }
}

//2.建堆
void CreateHeap(int* arr, int n)
{
    //从第一个非叶子节点开始建堆(最后一个非叶子节点,即为最后一个节点的父节点)
    int end = n - 1;
    int unleaf = (end - 1) / 2;
    while (unleaf >= 0)
    {
        ShiftDown(arr, n, unleaf);
        unleaf--;
    }
}

2. 堆排序

2.1 基本思想
堆排序属于交换排序,每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的末尾位置(即后面得到了已排序序列),直到全部待排序的数据元素排完。

2.2 堆排序算法步骤

  1. 建堆(升序:建最大堆;降序:建最小堆);
  2. 交换堆顶元素与最后一个未排序元素(初始end=n-1)——(交换完毕后,说明区间(end,n-1]已为有序区间);
  3. 重新调整堆(原因:堆顶元素发生改变),时期仍然是最大堆或最小堆;
  4. 重复2、3步骤,直到所有数据均有序,即end==0。

2.3 堆排序代码

void HeapSort(int* arr, int n)
{
    for (int i = n-1; i >0; --i)
    {
        swap(&arr[0], &arr[i]);
        ShiftDown(arr,i,0);             //调整函数——调整堆顶元素到合适位置
    }
}

2.4 算法特性

  1. 时间复杂度:O(N*logN)
  2. 空间复杂度:O(1)
  3. 稳定性:不稳定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值