数据结构与算法之数据结构 堆复杂度 插入 / 删除 / 调整

数据结构与算法阿木 发布于 2025-07-11 8 次阅读


摘要:

堆(Heap)是一种特殊的数据结构,它是一种近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或大于)它的父节点。堆常用于实现优先队列,在算法设计中有着广泛的应用。本文将深入探讨堆数据结构,包括其基本概念、实现方式、以及插入、删除和调整操作的复杂度分析。

一、堆的基本概念

1. 堆的定义

堆是一种特殊的完全二叉树,它满足以下性质:

(1)最大堆:每个父节点的值都大于或等于其子节点的值。

(2)最小堆:每个父节点的值都小于或等于其子节点的值。

2. 堆的存储结构

堆通常使用数组来存储,假设堆的根节点存储在数组中的索引为0,则对于任意节点i,其左子节点的索引为2i+1,右子节点的索引为2i+2。

二、堆的插入操作

1. 插入操作步骤

(1)将新元素添加到堆的末尾。

(2)通过上浮操作调整堆,使得新元素满足堆的性质。

2. 插入操作代码实现

python

def heap_insert(heap, element):


heap.append(element)


index = len(heap) - 1


while index > 0:


parent_index = (index - 1) // 2


if heap[parent_index] < heap[index]:


heap[parent_index], heap[index] = heap[index], heap[parent_index]


index = parent_index


else:


break


3. 插入操作复杂度分析

插入操作的时间复杂度为O(logn),其中n为堆中元素的数量。这是因为插入操作需要通过上浮操作调整堆,而上浮操作最多需要向上移动logn次。

三、堆的删除操作

1. 删除操作步骤

(1)删除堆顶元素,即数组的第一个元素。

(2)将堆的最后一个元素移动到堆顶。

(3)通过下沉操作调整堆,使得堆顶元素满足堆的性质。

2. 删除操作代码实现

python

def heap_delete(heap):


if len(heap) == 0:


return None


if len(heap) == 1:


return heap.pop()


heap[0] = heap.pop()


index = 0


while True:


left_child_index = 2 index + 1


right_child_index = 2 index + 2


largest_index = index


if left_child_index < len(heap) and heap[left_child_index] > heap[largest_index]:


largest_index = left_child_index


if right_child_index < len(heap) and heap[right_child_index] > heap[largest_index]:


largest_index = right_child_index


if largest_index == index:


break


heap[index], heap[largest_index] = heap[largest_index], heap[index]


index = largest_index


return heap[0]


3. 删除操作复杂度分析

删除操作的时间复杂度为O(logn),其中n为堆中元素的数量。这是因为删除操作需要通过下沉操作调整堆,而下沉操作最多需要向下移动logn次。

四、堆的调整操作

1. 调整操作步骤

(1)根据需要调整堆的性质(最大堆或最小堆)。

(2)通过上浮或下沉操作调整堆,使得堆满足调整后的性质。

2. 调整操作代码实现

python

def heap_adjust(heap, index, heap_type):


if heap_type == "max":


while index < len(heap):


left_child_index = 2 index + 1


right_child_index = 2 index + 2


largest_index = index


if left_child_index < len(heap) and heap[left_child_index] > heap[largest_index]:


largest_index = left_child_index


if right_child_index < len(heap) and heap[right_child_index] > heap[largest_index]:


largest_index = right_child_index


if largest_index == index:


break


heap[index], heap[largest_index] = heap[largest_index], heap[index]


index = largest_index


elif heap_type == "min":


while index < len(heap):


left_child_index = 2 index + 1


right_child_index = 2 index + 2


smallest_index = index


if left_child_index < len(heap) and heap[left_child_index] < heap[smallest_index]:


smallest_index = left_child_index


if right_child_index < len(heap) and heap[right_child_index] < heap[smallest_index]:


smallest_index = right_child_index


if smallest_index == index:


break


heap[index], heap[smallest_index] = heap[smallest_index], heap[index]


index = smallest_index


3. 调整操作复杂度分析

调整操作的时间复杂度为O(n),其中n为堆中元素的数量。这是因为调整操作需要对堆中的每个元素进行上浮或下沉操作,最多需要调整n次。

五、总结

本文深入探讨了堆数据结构及其相关操作,包括插入、删除和调整操作。通过分析这些操作的复杂度,我们可以更好地理解堆在算法设计中的应用。在实际应用中,堆数据结构因其高效性和实用性,被广泛应用于各种场景,如优先队列、排序算法等。