返回

探索堆的妙用:从理论到实践

IOS

在计算机科学的世界里,堆是一个独特的数据结构,它兼具数组和二叉树的特性。它的独到之处在于,它以一种特定的方式组织元素,这种方式使其在各种应用中都非常有用。

堆具有一个称为"堆属性"的重要特性,该特性决定了树中节点的排列顺序。它有两种类型:最大堆和最小堆,它们对树节点顺序的存储方式不同。

最大堆与最小堆

  • 最大堆: 每个父节点的值都大于或等于其子节点的值。这样,根节点将始终包含最大值。
  • 最小堆: 每个父节点的值都小于或等于其子节点的值。因此,根节点包含最小值。

堆的应用

堆的多功能性使其成为许多应用的理想选择,包括:

  • 构建优先队列: 堆可以高效地从队列中检索最大(或最小)元素,使优先队列得以实现。
  • 支持堆排序: 堆排序是一种利用堆属性对数组进行排序的高效算法。
  • 快速计算集合中的最大(或最小)值: 堆可以帮助快速查找集合中的最大或最小值,避免遍历整个集合。
  • 给你的非程序员朋友留下深刻影响: 堆的概念令人着迷且令人印象深刻,可以帮助你向外行人士展示计算机科学的强大功能。

构建你的第一个堆

构建堆的过程涉及将一组元素转换为满足堆属性的树形结构。对于最大堆,这个过程称为"heapify"。它从最后一个非叶节点开始,并对每一个节点进行下沉,直到满足堆属性。

代码示例

以下是用 Python 编写的一个最大堆示例:

class MaxHeap:
    def __init__(self):
        self.heap = []

    def heapify(self, arr):
        for i in range(len(arr) // 2 - 1, -1, -1):
            self.sift_down(i, len(arr))

    def sift_down(self, i, n):
        while 2 * i + 1 < n:
            left = 2 * i + 1
            right = 2 * i + 2
            max_child = left
            if right < n and self.heap[right] > self.heap[left]:
                max_child = right

            if self.heap[i] >= self.heap[max_child]:
                break

            self.heap[i], self.heap[max_child] = self.heap[max_child], self.heap[i]
            i = max_child

    def insert(self, value):
        self.heap.append(value)
        self.sift_up(len(self.heap) - 1)

    def sift_up(self, i):
        while i > 0:
            parent = (i - 1) // 2
            if self.heap[i] <= self.heap[parent]:
                break

            self.heap[i], self.heap[parent] = self.heap[parent], self.heap[i]
            i = parent

    def extract_max(self):
        if len(self.heap) == 0:
            return None

        max_value = self.heap[0]
        self.heap[0] = self.heap[-1]
        self.heap.pop()
        self.sift_down(0, len(self.heap))

        return max_value