golang,go,博客,开源,编程

Published on with 0 views and 0 comments

堆(Heap) 是一种特殊的完全二叉树,具有以下特点:每个节点的值都与其子节点的值存在某种特定的关系,通常有两种类型的堆:最大堆最小堆

  • 最大堆(Max-Heap):每个节点的值大于或等于其子节点的值,堆顶元素是所有元素中的最大值。
  • 最小堆(Min-Heap):每个节点的值小于或等于其子节点的值,堆顶元素是所有元素中的最小值。

1. 堆的基本特性

  • 完全二叉树:堆是完全二叉树,这意味着树的每一层都被填满,除最底层外,最底层的节点按从左到右的顺序排列。
  • 堆序性质
    • 最大堆:对于每个节点 i,都有 A[i] >= A[2i + 1]A[i] >= A[2i + 2](子节点的值小于等于父节点的值)。
    • 最小堆:对于每个节点 i,都有 A[i] <= A[2i + 1]A[i] <= A[2i + 2](子节点的值大于等于父节点的值)。

2. 堆的常见操作

堆提供了以下几种常见的操作:

1. 插入(Insert)

  • 将一个新元素插入堆中,插入后需要进行“上浮”操作(heapify-up),以确保堆序性质得以保持。
  • 对于最大堆,插入元素时,需要与父节点比较,如果插入的元素大于父节点,则交换它们的位置,直到堆序性质得到恢复。

2. 删除堆顶元素(Delete)

  • 删除堆顶元素并将堆的最后一个元素移到堆顶,然后执行“下沉”操作(heapify-down)来恢复堆的性质。
  • 对于最大堆,删除堆顶元素后,需要将堆底的最后一个元素移动到堆顶,并与其较大的子节点交换,直到恢复堆序性质。

3. 获取堆顶元素(Peek)

  • 获取并返回堆顶元素,最大堆返回最大元素,最小堆返回最小元素。此操作时间复杂度为 O(1)。

4. 堆化(Heapify)

  • 将一个无序数组转化为堆的过程。通常通过从最后一个非叶子节点开始,逐步向上执行“下沉”操作来恢复堆的性质。

3. 堆的实现

堆通常使用数组来实现。由于堆是完全二叉树,所以它的节点可以按顺序存储在数组中,且有如下关系:

  • 父节点索引:对于索引 i,其父节点的索引为 (i - 1) / 2
  • 左子节点索引:对于索引 i,其左子节点的索引为 2i + 1
  • 右子节点索引:对于索引 i,其右子节点的索引为 2i + 2

4. 堆的时间复杂度

操作时间复杂度
插入(Insert)O(log n)
删除堆顶元素(Delete)O(log n)
获取堆顶元素(Peek)O(1)
堆化(Heapify)O(n)
  • 插入和删除操作的时间复杂度是 O(log n),这是因为在最坏的情况下,需要沿着堆的高度(即树的深度)进行调整,堆的高度是 O(log n)。
  • 堆化操作(将一个无序数组转化为堆)需要从最后一个非叶子节点开始处理,并通过下沉操作逐步调整,最坏情况下需要 O(n) 时间。

5. 堆的应用

堆在很多算法和数据结构中都有广泛的应用,以下是一些典型的应用场景:

  1. 优先队列(Priority Queue)
    • 堆最常用于实现优先队列。优先队列是一个抽象数据类型,每个元素都有一个优先级,队列中优先级最高的元素会被优先取出。最大堆适用于最大优先队列,最小堆适用于最小优先队列。
  2. 堆排序(Heap Sort)
    • 堆排序是一种基于堆的排序算法,时间复杂度为 O(n log n)。首先将元素构建成一个堆,然后依次将堆顶元素与堆尾元素交换,再对剩余的元素进行堆化,直到所有元素排序完成。
  3. K个最小/最大元素
    • 在一个无序数组中,找出 K 个最小或最大元素,可以使用堆来高效实现。通过维护一个大小为 K 的堆,可以在 O(n log k) 时间内找到 K 个最小或最大元素。
  4. Dijkstra算法
    • 堆常用于图算法中,尤其是 Dijkstra 最短路径算法。在该算法中,堆用于高效地选择当前最短路径的节点。
  5. 动态中位数
    • 可以使用两个堆(一个最大堆和一个最小堆)来动态地计算一组数据的中位数。最大堆用于存储较小的一半数据,最小堆用于存储较大的一半数据。

6. 堆的优缺点

优点

  • 高效的插入与删除操作:堆可以在 O(log n) 时间内插入和删除元素,非常适合需要频繁插入和删除操作的场景。
  • 快速访问堆顶元素:堆顶元素可以在 O(1) 时间内访问,适合优先队列等应用。
  • 内存空间紧凑:堆通常使用数组实现,内存空间的利用率较高。

缺点

  • 不支持快速的任意元素访问:由于堆是一个树形结构,无法像数组一样支持 O(1) 的随机访问。
  • 结构较复杂:与简单的线性数据结构(如数组、链表)相比,堆的结构相对复杂,需要额外的操作来维护堆序性质。

7. 堆的实现(以最大堆为例)

#include <iostream>
#include <vector>
using namespace std;

class MaxHeap {
private:
    vector<int> heap;

    // 返回父节点的索引
    int parent(int i) { return (i - 1) / 2; }

    // 返回左子节点的索引
    int left(int i) { return 2 * i + 1; }

    // 返回右子节点的索引
    int right(int i) { return 2 * i + 2; }

    // 堆化操作(向下调整)
    void heapify(int i) {
        int l = left(i);
        int r = right(i);
        int largest = i;

        if (l < heap.size() && heap[l] > heap[largest]) largest = l;
        if (r < heap.size() && heap[r] > heap[largest]) largest = r;

        if (largest != i) {
            swap(heap[i], heap[largest]);
            heapify(largest);
        }
    }

public:
    // 插入元素
    void insert(int val) {
        heap.push_back(val);
        int i = heap.size() - 1;

        // 向上调整(上浮)
        while (i > 0 && heap[parent(i)] < heap[i]) {
            swap(heap[i], heap[parent(i)]);
            i = parent(i);
        }
    }

    // 删除堆顶元素
    void extractMax() {
        if (heap.empty()) {
            cout << "Heap is empty!" << endl;
            return;
        }
        heap[0] = heap.back();
        heap.pop_back();
        heapify(0);
    }

    // 获取堆顶元素
    int getMax() {
        if (!heap.empty()) return heap[0];
        return -1;  // 空堆返回 -1
    }

    // 堆化数组
    void buildHeap(vector<int>& arr) {
        heap = arr;
        for (int i = heap.size() / 2 - 1; i >= 0; --i) {
            heapify(i);
        }
    }

    // 打印堆
    void printHeap() {
        for (int val : heap) {
            cout << val << " ";
     

} cout << endl; } };

int main() { MaxHeap mh; mh.insert(10); mh.insert(20); mh.insert(15); mh.insert(30); mh.insert(40);

mh.printHeap(); // 打印堆

cout << "Max element: " << mh.getMax() << endl;

mh.extractMax();
mh.printHeap(); // 删除堆顶元素后打印堆

return 0;

}


### 8. **总结**

堆是一种高效的数据结构,广泛应用于优先队列、排序、图算法等场景。通过使用堆,可以有效地管理一组元素中的最大或最小值。堆的插入、删除操作具有 O(log n) 的时间复杂度,堆顶元素可以在 O(1) 时间内访问,适合需要频繁插入和删除操作的应用场景。

标题:堆
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/10/1736471250049.html
联系:scotttu@163.com