返回

解开算法数据结构之堆的奥秘:特性、应用和代码示例

见解分享

堆是一种数据结构,它满足两个基本性质:

  1. 堆必须是一个完全二叉树。完全二叉树是指除了最后一层,其它层的结点个数都是满的,最后一层的结点都靠左排列。

  2. 堆中的每个结点的值必须大于等于(或小于等于)其子树中每个结点的值。

堆可以分为两种类型:最小堆和最大堆。

  1. 在最小堆中,每个结点的值都小于或等于其子树中每个结点的值。最小堆的根结点是最小的元素。

  2. 在最大堆中,每个结点的值都大于或等于其子树中每个结点的值。最大堆的根结点是最大的元素。

堆在计算机科学中有着广泛的应用,例如:

  1. 堆排序:堆排序是一种基于堆的数据结构进行排序的算法。它是一种非比较排序算法,其时间复杂度为 O(n log n)。

  2. 优先队列:优先队列是一种允许对元素按其优先级进行排序的队列。在优先队列中,优先级最高的元素总是第一个被检索到。堆是一种常用的优先队列实现方式。

  3. 堆查找:堆查找是一种在堆中查找元素的算法。堆查找的时间复杂度为 O(log n)。

以下是用 C++ 实现堆的代码示例:

class Heap {
public:
  Heap(int capacity) {
    this->capacity = capacity;
    this->size = 0;
    this->heap = new int[capacity];
  }

  ~Heap() {
    delete[] this->heap;
  }

  int size() {
    return this->size;
  }

  bool isEmpty() {
    return this->size == 0;
  }

  int top() {
    if (this->isEmpty()) {
      throw "Heap is empty";
    }
    return this->heap[0];
  }

  void push(int value) {
    if (this->size == this->capacity) {
      throw "Heap is full";
    }
    this->heap[this->size] = value;
    this->size++;
    this->heapifyUp(this->size - 1);
  }

  int pop() {
    if (this->isEmpty()) {
      throw "Heap is empty";
    }
    int value = this->heap[0];
    this->heap[0] = this->heap[this->size - 1];
    this->size--;
    this->heapifyDown(0);
    return value;
  }

private:
  int capacity;
  int size;
  int* heap;

  void heapifyUp(int index) {
    while (index > 0) {
      int parentIndex = (index - 1) / 2;
      if (this->heap[index] < this->heap[parentIndex]) {
        swap(this->heap[index], this->heap[parentIndex]);
        index = parentIndex;
      } else {
        break;
      }
    }
  }

  void heapifyDown(int index) {
    while (2 * index + 1 < this->size) {
      int leftChildIndex = 2 * index + 1;
      int rightChildIndex = 2 * index + 2;
      int smallestChildIndex = leftChildIndex;
      if (rightChildIndex < this->size && this->heap[rightChildIndex] < this->heap[leftChildIndex]) {
        smallestChildIndex = rightChildIndex;
      }
      if (this->heap[index] > this->heap[smallestChildIndex]) {
        swap(this->heap[index], this->heap[smallestChildIndex]);
        index = smallestChildIndex;
      } else {
        break;
      }
    }
  }
};

这个代码示例演示了如何使用堆来存储和管理数据。它提供了一个简单的界面,允许用户轻松地向堆中添加和删除数据,以及检索堆中的最大或最小元素。