数据结构排序算法—堆排序

核心思想

堆排序(Heap Sort)是一种基于完全二叉树结构的排序算法,利用堆的性质进行排序。其核心思想分为两个阶段:

  1. 构建堆:将无序数组构建成一个大顶堆(最大堆)或小顶堆(最小堆)

  2. 排序阶段:通过反复交换堆顶元素与末尾元素,并调整堆结构,逐步将极值元素移到有序区


算法特性

  • 时间复杂度:始终为 O(n log n),无论数据是否有序

  • 空间复杂度O(1),原地排序算法

  • 稳定性不稳定(堆调整过程可能破坏相等元素的相对顺序)

  • 适用场景

    • 需要保证最坏情况时间复杂度时

    • 不适合小规模数据(常数因子较大)

    • 内存敏感场景(原地排序)


算法步骤

  •  Python实现
     

    def heap_sort(arr):
        def heapify(arr, n, i):
            largest = i
            l = 2 * i + 1  # 左子节点索引
            r = 2 * i + 2  # 右子节点索引
    
            # 找出三者中的最大值
            if l < n and arr[l] > arr[largest]:
                largest = l
            if r < n and arr[r] > arr[largest]:
                largest = r
    
            # 若最大值不在根节点,交换并递归调整
            if largest != i:
                arr[i], arr[largest] = arr[largest], arr[i]
                heapify(arr, n, largest)
    
        n = len(arr)
    
        # 构建最大堆(从最后一个非叶子节点开始)
        for i in range(n//2 - 1, -1, -1):
            heapify(arr, n, i)
    
        # 逐个提取元素
        for i in range(n-1, 0, -1):
            arr[i], arr[0] = arr[0], arr[i]  # 交换堆顶与末尾元素
            heapify(arr, i, 0)  # 调整缩小后的堆
    
        return arr
  • C++实现
     

    #include <iostream>
    #include <vector>
    using namespace std;
    
    void heapify(vector<int>& arr, int n, int i) {
        int largest = i;
        int l = 2 * i + 1;
        int r = 2 * i + 2;
    
        if (l < n && arr[l] > arr[largest])
            largest = l;
        if (r < n && arr[r] > arr[largest])
            largest = r;
    
        if (largest != i) {
            swap(arr[i], arr[largest]);
            heapify(arr, n, largest);
        }
    }
    
    void heap_sort(vector<int>& arr) {
        int n = arr.size();
        
        // 构建最大堆
        for (int i = n/2 - 1; i >= 0; i--)
            heapify(arr, n, i);
    
        // 逐个提取元素
        for (int i = n-1; i > 0; i--) {
            swap(arr[0], arr[i]);
            heapify(arr, i, 0);
        }
    }

  •         将堆顶元素(最大值)与末尾元素交换
    • 缩小堆范围,重新调整堆结构

    • 重复直到堆大小为1
      关键步骤解析

    • 堆的构建(heapify)

      • 时间复杂度分析:看似为O(n log n),实际通过Floyd算法优化为O(n)

      • 调整过程:从当前节点向下递归调整,保证父节点始终大于子节点

    • 排序阶段

      • 交换操作:每次将堆顶最大值交换到数组末尾

      • 堆范围缩小:排序好的末尾元素不再参与后续堆调整

    • 索引计算

      • 父节点i的左子节点:2i + 1

      • 父节点i的右子节点:2i + 2

      • 子节点i的父节点:(i-1)//2


    • 可视化示例

      原始数组:[4, 10, 3, 5, 1]

    • 构建堆过程:

    •        4              10             10
           /   \          /   \         /   \
          10    3   →    5     3   →   5     4
         / \            / \           /
        5   1          4   1         1
    • 排序过程:

    • 交换10和1 → 调整堆 → 交换5和1 → 调整堆 → ... → 最终有序

      性能优化方向

    • 迭代实现heapify:避免递归调用栈开销


    • 堆排序将数据视为完全二叉树进行处理,既保持了选择排序的简单性,又通过堆结构将时间复杂度优化到O(n log n)级别,是理解树形结构在排序中应用的经典案例。

    • 内存访问优化:利用缓存友好的访问模式

    • 多叉堆:根据硬件特性调整子节点数量

    • 混合排序:结合插入排序处理小规模子序列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MTXi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值