python堆-完全二叉树--完全解读

简介: python堆-完全二叉树--完全解读

⭐️堆

Python中的堆是通过heapq模块实现的。这个模块提供了一种高效的方式来创建和管理堆数据结构。堆是一种二叉树,其中树完全填充,只有最底层可能从左到右不完全填充。

为什么使用 heapq?

Python的heapq模块使用普通列表实现了最小堆。最小堆确保最小的元素始终在根部(即heap[0])。heapq模块提供了操作堆的函数,同时保持堆属性不变

它是如何工作的?

在底层,heapq利用了二叉堆的属性。二叉堆是一个完全二叉树,满足堆属性。在最小堆中,父节点小于其子节点。这个属性对于每个节点都必须是真的,这使得根部成为堆中最小的元素

使用heapq的基本操作

创建堆:

你从一个空列表开始,然后使用heapq.heappush()添加元素。这个函数添加元素的同时重新排列堆,以保持堆属性。

import heapq
minHeap = []
heapq.heappush(minHeap, 3)
heapq.heappush(minHeap, 1)
heapq.heappush(minHeap, 2)

这些操作之后,minHeap将会是[1, 3, 2]。最小元素(1)在根部

访问最小元素:

最小元素始终可以在minHeap[0]找到。这是一个常数时间操作

移除最小元素:

使用heapq.heappop()移除并返回最小元素。这个操作也会重新排列堆以保持其属性。

smallest_element = heapq.heappop(minHeap)  # 移除并返回 '1'

Heapify:

如果你有一个现有列表,你可以使用heapq.heapify()将其转换为堆。这会重新排列元素以满足堆属性

some_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
heapq.heapify(some_list)

现在some_list是一个堆

效率

堆在不断需要访问最小(或在最大堆的情况下是最大)元素的任务中非常高效插入和删除的时间复杂度为O(log n),访问最小元素的时间复杂度为O(1)。

应用

堆被用在算法中,如堆排序,在优先队列中,用于高效地找到列表中的第k个最小/最大元素,以及在图算法中,如迪杰斯特拉(Dijkstra)最短路径算法

当然可以。我会给出几个Python中使用heapq模块的示例代码,以展示堆的一些常见应用。

1. 堆排序(Heap Sort)

import heapq
def heap_sort(nums):
    heapq.heapify(nums)  # 将列表转换为堆
    return [heapq.heappop(nums) for _ in range(len(nums))]
# 示例
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5]
sorted_nums = heap_sort(nums)
print(sorted_nums)

2. 使用堆实现优先队列

import heapq
class PriorityQueue:
    def __init__(self):
        self.heap = []
    def push(self, item, priority):
        heapq.heappush(self.heap, (priority, item))
    def pop(self):
        return heapq.heappop(self.heap)[1]
# 示例
pq = PriorityQueue()
pq.push('任务1', 3)
pq.push('任务2', 1)
pq.push('任务3', 2)
while pq.heap:
    print(pq.pop())

3. 查找列表中第k个最小元素

import heapq
def kth_smallest(nums, k):
    return heapq.nsmallest(k, nums)[-1]
# 示例
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5]
k = 4
print(kth_smallest(nums, k))

4. 使用堆实现Dijkstra算法(简化版)

import heapq
def dijkstra(graph, start):
    # 初始化距离表,所有距离设为无穷大
    distances = {vertex: float('infinity') for vertex in graph}
    distances[start] = 0
    # 创建一个优先队列,并把起始顶点放入队列中
    pq = [(0, start)]
    while pq:
        current_distance, current_vertex = heapq.heappop(pq)
        # 跳过处理已经找到更短路径的节点
        if current_distance > distances[current_vertex]:
            continue
        for neighbor, weight in graph[current_vertex].items():
            distance = current_distance + weight
            # 更新距离表
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(pq, (distance, neighbor))
    return distances
# 示例图
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 1, 'C': 2, 'D': 5},
    'C': {'A': 4, 'B': 2, 'D': 1},
    'D': {'B': 5, 'C': 1}
}
print(dijkstra(graph, 'A'))

这些示例覆盖了堆的一些基本用法,包括排序、优先队列、查找特定元素和图算法。通过这些示例,可以更好地理解堆的实用性和在算法中的应用。

您给出的这个结构是一个图的表示方式,

具体来说,它是一个带权重的有向图的字典表示形式。在这个字典中,每个键(例如 ‘A’, ‘B’, ‘C’, ‘D’)代表图中的一个顶点,而与每个键相关联的字典则表示从该顶点出发到其他顶点的边及其相应的权重

这种表示方式非常适合用来描述图的结构,特别是当你需要实现图的算法(如路径查找、网络流分析等)时。这里是如何解读这个图:

顶点 ‘A’ 有两条边,一条通向 ‘B’,权重为 1,另一条通向 ‘C’,权重为 4。

顶点 ‘B’ 有三条边,分别通向 ‘A’(权重为 1)、‘C’(权重为 2)和 ‘D’(权重为 5)。

顶点 ‘C’ 有三条边,分别通向 ‘A’(权重为 4)、‘B’(权重为 2)和 ‘D’(权重为 1)。

顶点 ‘D’ 有两条边,一条通向 ‘B’,权重为 5,另一条通向 ‘C’,权重为 1。

这种表示法是图论和网络分析中常用的,尤其是在编程和算法设计时。例如,你可以用这个图来实现Dijkstra算法,寻找从一个顶点到另一个顶点的最短路径

kth_smallest 使用了 Python 的 heapq 模块来找到一个列表中第 k 个最小的元素。这个函数的工作原理如下:

  1. heapq.nsmallest(k, nums):这个函数调用从 nums 列表中找到 k 个最小的元素。内部实现上,它首先将列表转换成一个最小堆,然后一次取出最小元素直到取出 k 个。
  2. [-1]:这部分从由 nsmallest 返回的列表中取出最后一个元素。由于这个列表是有序的,最后一个元素就是这 k 个最小元素中最大的一个,也就是整个列表中第 k 个最小的元素。

这个函数的时间复杂度取决于 heapq.nsmallest 函数的实现,通常情况下这个操作的时间复杂度是 O(n log k),其中 n 是列表 nums 的长度。

这里是一个使用示例:

import heapq
def kth_smallest(nums, k):
    return heapq.nsmallest(k, nums)[-1]
# 示例
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5]
k = 4
print(kth_smallest(nums, k))  # 输出第4个最小的元素

在这个例子中,kth_smallest(nums, k) 会返回列表 nums 中第 4 个最小的元素。

相关文章
|
6月前
|
算法 程序员 调度
python堆(Heapq)
python堆(Heapq)
63 3
|
JavaScript Python 内存技术
error C:\Users\Acer\Downloads\Desktop\hrsaas-84\node_modules\deasync: 莫名其妙报错一堆python问题
error C:\Users\Acer\Downloads\Desktop\hrsaas-84\node_modules\deasync: 莫名其妙报错一堆python问题
201 0
|
4月前
|
算法 安全 大数据
揭秘!Python堆与优先队列:数据结构的秘密武器,让你的代码秒变高效战士!
【7月更文挑战第8天】Python的heapq模块和queue.PriorityQueue提供堆与优先队列功能,助你提升算法效率。堆用于快速找大数据集的第K大元素,如示例所示,时间复杂度O(n log k)。PriorityQueue在多线程中智能调度任务,如模拟下载管理器,按优先级处理任务。掌握这些工具,让代码运行更高效!
70 1
|
4月前
|
算法 大数据 数据处理
震撼!Python堆与优先队列的神奇力量,让你的数据处理能力瞬间爆表!
【7月更文挑战第9天】Python的heapq模块实现了堆数据结构,用于高效地插入、删除和查找最大/最小元素。在Top K元素查找中,堆能快速找到大数据集的前k个最大值。同样,堆作为优先队列,按优先级而非入队顺序处理任务,如任务调度,展示其在复杂问题解决中的效率。掌握这些工具,能显著提升数据处理和编程效率。
46 3
|
4月前
|
存储 算法 调度
惊呆了!Python高级数据结构堆与优先队列,竟然能这样优化你的程序性能!
【7月更文挑战第10天】Python的heapq模块实现了堆和优先队列,提供heappush和heappop等函数,支持O(log n)时间复杂度的操作。优先队列常用于任务调度和图算法,优化性能。例如,Dijkstra算法利用最小堆加速路径查找。堆通过列表存储,内存效率高。示例展示了添加、弹出和自定义优先级元素。使用堆优化程序,提升效率。
60 2
|
4月前
|
存储 大数据 程序员
逆袭吧,程序员!Python堆与优先队列的使用秘籍,助你轻松解决复杂问题!
【7月更文挑战第9天】Python的堆和优先队列是高效工具,对比列表在删除最小元素时的O(n)复杂度,堆提供O(log n)操作。优先队列利用堆数据结构,按优先级处理元素,而非FIFO。示例中,heapq模odule创建最小堆实现任务优先级执行,显示了其在解决复杂问题时的威力,助力程序员提升效率,实现编程挑战的逆袭。
47 2
|
4月前
|
算法 调度 Python
Python高手必备!堆与优先队列的高级应用,掌握它们,技术路上畅通无阻!
【7月更文挑战第9天】Python的heapq模块实现了堆数据结构,提供O(log n)操作如`heappush`和`heappop`。堆是完全二叉树,用于优先队列,保证最大/最小元素快速访问。例如,最小堆弹出最小元素,常用于Dijkstra算法找最短路径、Huffman编码压缩数据及任务调度。通过`heappush`和`heappop`可创建和管理优先队列,如`(优先级, 数据)`元组形式。理解并运用这些概念能优化算法效率,解决复杂问题。
47 2
|
4月前
|
存储 算法 调度
从菜鸟到大神的蜕变之路:Python堆与优先队列,掌握它们,你就是技术圈的MVP!
【7月更文挑战第10天】在编程进阶中,Python的heapq模块提供堆(Heap)和优先队列(Priority Queue)功能,助力高效编程。堆是特殊的完全二叉树,优先队列基于堆实现,用于按优先级处理元素。
40 0
|
4月前
|
算法 调度 索引
Python堆与优先队列大起底:深入骨髓的解析,让你彻底告别低效编程!
【7月更文挑战第9天】Python的heapq模块实现了堆数据结构,提供heappush和heappop等操作,支持最小堆。堆是完全二叉树,满足堆属性。优先队列利用堆实现,元素按优先级出队。通过将优先级和元素打包入堆,如示例所示,能轻松处理优先级任务。掌握堆与优先队列,提升编程效率。
37 0
|
4月前
|
算法 安全 调度
逆天改命!Python高级数据结构堆(Heap)与优先队列,让你的算法效率飙升至宇宙级!
【7月更文挑战第8天】Python的heapq模块和queue.PriorityQueue实现了堆和优先队列,提供高效算法解决方案。堆用于Dijkstra算法求解最短路径,例如在图论问题中;PriorityQueue则在多线程下载管理中确保高优先级任务优先执行。这两个数据结构提升效率,简化代码,是编程中的强大工具。
50 0