堆,堆排序原理

你问的是数据结构里的“堆”,并想深入理解它 结构原理 + 操作逻辑 + 排序实现——这正是面试、刷题、项目中常考的重点数据结构之一,尤其在优先队列、堆排序、TopK 等场景频繁出现。

下面我来系统讲透堆(Heap)👇


🧠 一、什么是“堆”(Heap)

堆是一棵特殊的完全二叉树(Complete Binary Tree),满足以下性质:

  • 大顶堆(Max-Heap):父节点 ≥ 子节点
  • 小顶堆(Min-Heap):父节点 ≤ 子节点

💡 完全二叉树 → 除最后一层外都是满的,最后一层从左到右填满


✅ 二、堆的存储结构:用数组实现

虽然是二叉树,但实际堆都用数组来实现

数组下标和节点关系:

节点下标左子节点右子节点父节点
i2i + 12i + 2(i - 1)/2

🚀 三、堆的基本操作

🔼 插入元素(heapify up)

  1. 把新元素插在数组末尾;
  2. 与父节点比较,若违反堆性质就向上交换;
  3. 直到恢复堆结构。

时间复杂度:O(log n)


🔽 删除堆顶(heapify down)

  1. 删除堆顶(数组第一个元素);
  2. 用最后一个元素顶上去;
  3. 与左右孩子比较并下沉,直到满足堆性质。

时间复杂度:O(log n)


✍️ 四、代码演示(手动实现最小堆)

#include <vector>
#include <iostream>

class MinHeap {
    std::vector<int> data;

    void heapify_up(int i) {
        while (i > 0 && data[i] < data[(i - 1) / 2]) {
            std::swap(data[i], data[(i - 1) / 2]);
            i = (i - 1) / 2;
        }
    }

    void heapify_down(int i) {
        int n = data.size();
        while (true) {
            int smallest = i;
            int l = 2 * i + 1, r = 2 * i + 2;
            if (l < n && data[l] < data[smallest]) smallest = l;
            if (r < n && data[r] < data[smallest]) smallest = r;
            if (smallest == i) break;
            std::swap(data[i], data[smallest]);
            i = smallest;
        }
    }

public:
    void push(int val) {
        data.push_back(val);
        heapify_up(data.size() - 1);
    }

    void pop() {
        std::swap(data[0], data.back());
        data.pop_back();
        heapify_down(0);
    }

    int top() const { return data[0]; }

    bool empty() const { return data.empty(); }
};

📦 五、堆排序(Heap Sort)

堆排序 = 先建堆 + 反复取堆顶 + 调整堆结构

✨ 思路:

  1. 将数组建立为 最大堆(build heap)
  2. 交换堆顶与末尾元素
  3. 将剩余部分继续调整为最大堆
  4. 重复直到排序完成

✅ 时间复杂度:

操作时间复杂度
建堆O(n)
每次调整堆O(log n)
总体排序复杂度O(n log n)

📌 特点:

  • 原地排序,不需要额外空间(O(1))
  • 非稳定排序
  • 最坏、最好、平均时间复杂度都是 O(n log n)

🔁 堆排序代码示例(从数组中排序)

#include <iostream>
#include <vector>
#include <algorithm>

void heapify(std::vector<int>& arr, int n, int i) {
    int largest = i, l = 2*i + 1, 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) {
        std::swap(arr[i], arr[largest]);
        heapify(arr, n, largest);
    }
}

void heap_sort(std::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--) {
        std::swap(arr[0], arr[i]);      // 把最大值放最后
        heapify(arr, i, 0);             // 剩下部分建堆
    }
}

✅ 面试总结模板(可背):

堆是一种满足“父节点 ≥ 子节点(或 ≤)”的完全二叉树,通常用数组实现,支持高效地插入元素和获取最大/最小值,时间复杂度是 O(log n)。堆在 C++ 中广泛应用于优先队列、TopK 问题、任务调度等场景,堆排序基于最大堆实现,整体时间复杂度为 O(n log n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值