返回

堆:数据结构中的顺序存储树

后端

在数据结构(四):二叉树中,我们探索了使用链式结构实现树。在本篇中,我们将介绍堆,一种使用顺序结构实现的特殊树形数据结构。

为什么要用顺序存储?

堆是一种完全二叉树,这意味着每个节点都有 0 个或 2 个子节点。这种结构允许我们使用数组进行顺序存储,从而避免了链式结构中指针带来的开销和内存碎片。

堆的特性

堆具有以下特性:

  • 完全二叉树: 所有级别(除了最底层)都完全填充。
  • 堆序: 对于任意节点,其子节点的值都小于(或大于)其自身的值,形成最大堆(或最小堆)。

堆的操作

堆支持以下操作:

  • 插入: 将新元素插入堆并维护堆序。
  • 删除: 从堆中删除根元素并维护堆序。
  • 查找: 找到堆中最大(或最小)的元素。

堆的应用

堆在计算机科学中广泛应用于:

  • 优先级队列: 用于存储具有不同优先级的元素。
  • 排序算法: 堆排序是一种使用堆进行排序的有效算法。
  • 数据结构: 堆可以作为其他数据结构(如优先级队列和散列表)的基础。

代码示例

以下是一个在 C++ 中实现最大堆的代码示例:

#include <vector>

class MaxHeap {
private:
    std::vector<int> heap;

public:
    // 插入
    void insert(int value) {
        heap.push_back(value);
        heapifyUp(heap.size() - 1);
    }

    // 删除
    int removeMax() {
        int max = heap[0];
        heap[0] = heap[heap.size() - 1];
        heap.pop_back();
        heapifyDown(0);
        return max;
    }

    // 查找最大值
    int getMax() {
        return heap[0];
    }

private:
    // 从下往上维护堆序
    void heapifyUp(int index) {
        while (index > 0) {
            int parent = (index - 1) / 2;
            if (heap[index] > heap[parent]) {
                swap(heap[index], heap[parent]);
                index = parent;
            } else {
                break;
            }
        }
    }

    // 从上往下维护堆序
    void heapifyDown(int index) {
        while (index < heap.size()) {
            int left = 2 * index + 1;
            int right = 2 * index + 2;
            int largest = index;
            if (left < heap.size() && heap[left] > heap[largest]) {
                largest = left;
            }
            if (right < heap.size() && heap[right] > heap[largest]) {
                largest = right;
            }
            if (largest != index) {
                swap(heap[index], heap[largest]);
                index = largest;
            } else {
                break;
            }
        }
    }
};

总结

堆是一种使用顺序存储实现的完全二叉树,具有堆序特性。它支持高效的插入、删除和查找操作,在计算机科学中广泛应用于优先级队列、排序算法和数据结构。