📜  堆 (1)

📅  最后修改于: 2023-12-03 15:37:49.600000             🧑  作者: Mango

介绍

在计算机科学中,堆是一种重要的数据结构。堆是一个可以被看做一棵树的数组对象,其父子节点关系定义了堆的属性。堆的一个重要应用是实现堆排序。

堆有两种类型: 最大堆和最小堆。最大堆是一种特别的二叉树,其中每个父节点的值都大于或等于其所有子节点的值。而最小堆则是每个父节点的值都小于或等于其所有子节点的值。因此,在最大堆中,根节点始终是最大的。在最小堆中,根节点始终是最小值。堆排序是一种基于堆的排序算法,它会使用最大堆或最小堆来完成排序。

堆排序的时间复杂度是 $\Theta(n\log n)$,优于冒泡排序和插入排序的 $\Theta(n^2)$ 时间复杂度。因此,堆在计算机科学中是一个非常有用的结构。

实现

堆可以通过一个数组来实现。对于一个给定的节点 $i$ 的父节点和子节点的下标可以通过以下公式计算:

  • 父节点:$\lfloor i/2 \rfloor$
  • 左子节点:$2i$
  • 右子节点:$2i + 1$

堆常用的操作有插入、删除、建堆、堆排序。其中插入和删除操作的时间复杂度均为 $\Theta(\log n)$,而建堆操作的时间复杂度是 $\Theta(n)$。

以下是使用 Python 语言实现的一个最小堆:

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

    def insert(self, val):
        """
        插入一个新元素到最小堆中
        """
        self.heap.append(val)
        self.bubble_up()

    def delete_min(self):
        """
        删除堆中最小的元素
        """
        if len(self.heap) == 0:
            return None

        min_val = self.heap[0]
        self.heap[0] = self.heap[-1] # 将最后一个元素放到根节点
        self.heap.pop() # 将最后一个元素删除
        self.bubble_down()

        return min_val

    def bubble_up(self):
        """
        将插入的元素上移,直到满足堆的性质
        """
        idx = len(self.heap) - 1

        while idx > 0:
            parent_idx = (idx - 1) // 2
            if self.heap[parent_idx] > self.heap[idx]:
                self.heap[parent_idx], self.heap[idx] = self.heap[idx], self.heap[parent_idx]
                idx = parent_idx
            else:
                break

    def bubble_down(self):
        """
        将删除最小元素后的最后一个元素下移,直到满足堆的性质
        """
        idx = 0

        while idx * 2 + 1 < len(self.heap):
            min_child_idx = self.get_min_child_idx(idx)
            if self.heap[idx] > self.heap[min_child_idx]:
                self.heap[idx], self.heap[min_child_idx] = self.heap[min_child_idx], self.heap[idx]
                idx = min_child_idx
            else:
                break

    def get_min_child_idx(self, idx):
        """
        获取最小的子节点
        """
        left_child_idx = idx * 2 + 1
        right_child_idx = idx * 2 + 2

        if right_child_idx >= len(self.heap):
            return left_child_idx
        else:
            if self.heap[left_child_idx] < self.heap[right_child_idx]:
                return left_child_idx
            else:
                return right_child_idx
结论

堆是计算机科学中一种重要的数据结构,它在算法和数据处理方面有着广泛的应用。堆中最值的属性使得堆在搜索、排序、和图模型的算法中非常实用。堆排序是一种时间复杂度为 $\Theta(n\log n)$ 的高效排序算法。