📜  二叉堆(1)

📅  最后修改于: 2023-12-03 14:49:01.027000             🧑  作者: Mango

二叉堆

二叉堆是一种特殊的树形数据结构,由于其优秀的时间复杂度表现,在计算机科学中得到了广泛的使用。它分为两种:最大堆和最小堆,根据不同的表现行为用途也不同。

结构

二叉堆通常是用一个数组来表示,每个节点对应数组中的一个元素。对于第$i$个元素:

  • 它的左儿子在位置$2i+1$
  • 它的右儿子在位置$2i+2$
  • 它的父节点在位置$\lfloor\frac{i-1}{2}\rfloor$

最大堆的结构定义为:

class MaxHeap:
    def __init__(self):
        self.heap = []
    
    def parent(self, i):
        return (i - 1) // 2
    
    def left_child(self, i):
        return 2 * i + 1
    
    def right_child(self, i):
        return 2 * i + 2

最小堆的结构定义为:

class MinHeap:
    def __init__(self):
        self.heap = []
    
    def parent(self, i):
        return (i - 1) // 2
    
    def left_child(self, i):
        return 2 * i + 1
    
    def right_child(self, i):
        return 2 * i + 2
操作

二叉堆主要支持以下几种操作:

插入

在堆中插入一个元素,这一般是在堆的最后一个位置插入。然后,我们对这个元素进行一系列的比较操作,直到它到达合适的位置。对于最大堆,插入操作如下:

def insert(self, item):
    self.heap.append(item)
    i = len(self.heap) - 1
    while i > 0 and self.heap[self.parent(i)] < self.heap[i]:
        self.heap[self.parent(i)], self.heap[i] = \
            self.heap[i], self.heap[self.parent(i)]
        i = self.parent(i)

最小堆的插入操作如下:

def insert(self, item):
    self.heap.append(item)
    i = len(self.heap) - 1
    while i > 0 and self.heap[self.parent(i)] > self.heap[i]:
        self.heap[self.parent(i)], self.heap[i] = \
            self.heap[i], self.heap[self.parent(i)]
        i = self.parent(i)
删除

堆的删除操作是将堆顶元素(最大值或最小值)移除,然后将结构重整为新的堆。对于最大堆,删除操作如下:

def extract_max(self):
    result = self.heap[0]
    self.heap[0] = self.heap[-1]
    del self.heap[-1]
    self.max_heapify(0)
    return result
    
def max_heapify(self, i):
    left = self.left_child(i)
    right = self.right_child(i)
    largest = i
    if left < len(self.heap) and self.heap[left] > self.heap[largest]:
        largest = left
    if right < len(self.heap) and self.heap[right] > self.heap[largest]:
        largest = right
    if largest != i:
        self.heap[i], self.heap[largest] = self.heap[largest], self.heap[i]
        self.max_heapify(largest)

最小堆的删除操作如下:

def extract_min(self):
    result = self.heap[0]
    self.heap[0] = self.heap[-1]
    del self.heap[-1]
    self.min_heapify(0)
    return result
    
def min_heapify(self, i):
    left = self.left_child(i)
    right = self.right_child(i)
    smallest = i
    if left < len(self.heap) and self.heap[left] < self.heap[smallest]:
        smallest = left
    if right < len(self.heap) and self.heap[right] < self.heap[smallest]:
        smallest = right
    if smallest != i:
        self.heap[i], self.heap[smallest] = self.heap[smallest], self.heap[i]
        self.min_heapify(smallest)
构建

构建操作是将一个无序数组构建成一个堆。对于最大堆,构建操作如下:

def build_max_heap(self, arr):
    self.heap = arr
    i = len(self.heap) // 2
    while i >= 0:
        self.max_heapify(i)
        i -= 1

最小堆的构建操作如下:

def build_min_heap(self, arr):
    self.heap = arr
    i = len(self.heap) // 2
    while i >= 0:
        self.min_heapify(i)
        i -= 1
时间复杂度

二叉堆在最坏情况下具有$O(logn)$的时间复杂度,其中$n$为堆的大小。它的空间复杂度为$O(n)$。