Python 中的堆 (heapq 模块)应用:Merge K Sorted Lists

本文介绍了堆数据结构的基本概念,包括其定义、性质及应用。详细解释了如何使用Python的heapq模块来创建和操作堆,提供了创建堆的具体实例。此外还展示了如何利用堆来解决合并多个已排序列表的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        堆是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。

1 定义

n个元素序列{k1,k2...ki...kn},当且仅当满足下列关系时称之为堆:
(ki <= k2i, ki <= k2i+1)或者(ki >= k2i, ki >= k2i+1), (i = 1,2,3,4...n/2)

2 性质

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。

  • 任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
  • 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。

将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。

3 应用

 

3.1 heapq 模块中的重要函数

>>> import heapq
>>> heapq.__all__
['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop']
heappush(heap, x)       将 x 入堆
heappop(heap)           将堆属性中的最小元素弹出   
heapify(heap)           将 heap 属性强制应用到任意一个列表
heapreplace(heap, x)    将堆中的最小的元素弹出,同时将 x 入堆
merge()                 多个堆合并         
nlargest(n, iter)       返回 iter 中的第 n 大的元素
nsmallest(n, iter)      返回 iter 中的第 n 小的元素

3.2 创建堆结构

list1 = [3,2,8,1,4,5]
heapq.heapify(list1)

list2 = []
heapq.heappush(list2, 3)
heapq.heappush(list2, 2)
heapq.heappush(list2, 8)
heapq.heappush(list2, 1)
heapq.heappush(list2, 4)
heapq.heappush(list2, 5)
list1
Out[110]: [1, 2, 5, 3, 4, 8]
list2
Out[108]: [1, 2, 5, 3, 4, 8]

以上两种方法创建的堆是一样的,元素推入堆后会自动按照二叉树的规范重新排序

3.3 Merge K sorted Lists 

    用堆的思想合并k个排序链表,并且返回合并后的排序链表。

思路1:

    将所有链表的节点 push 到堆中,每次把最小的 pop 出来。代码如下:

"""
Definition of ListNode
class ListNode(object):


    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""
import heapq
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        heap = []
        for node in lists:
            while node:
                heapq.heappush(heap, node.val)
                node = node.next
                
        temp = ListNode(-1)
        head = temp
        while heap:
            smallestNode_val = heapq.heappop(heap)
            temp.next = ListNode(smallestNode_val)
            temp = temp.next
        
        return head.next

思路2:

    不用堆用列表也能实现,代码如下:

"""
Definition of ListNode
class ListNode(object):


    def __init__(self, val, next=None):
        self.val = val
        self.next = next
"""
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        l = []
        for node in lists:
            while node:
                l.append(node.val)
                node = node.next
        l.sort()
        temp = ListNode(-1)
        head = temp
        for i in l:
            temp.next = ListNode(i)
            temp = temp.next
        
        return head.next

 

 

 

参考资料:

heapq — Heap queue algorithm

 

 

 

 

 

 

### 关于 Python 列表的应用场景或练习题目 Python 中的 `list` 是一种非常灵活的数据结构,广泛应用于各种实际开发需求和算法实现中。以下是几个常见的应用场景以及一些经典的练习题: #### 应用场景 1. **动态数组** 列表支持动态扩展大小,因此非常适合用于存储数量不确定的对象集合。 2. **栈操作** 可以通过 `.append()` 和 `.pop()` 方法轻松实现栈的功能。 3. **队列操作** 虽然列表不是最优的队列实现方式,但仍可以通过 `.insert(0, value)` 和 `.pop()` 来模拟队列行为[^1]。 4. **排序与查找** 利用内置方法如 `.sort()` 或函数 `sorted()` 对列表进行排序;或者利用循环遍历完成线性查找。 --- #### 经典练习题 ##### 题目 1: 去重并保持顺序 给定一个包含重复元素的列表 `[1, 2, 3, 2, 4, 5, 1]`,编写程序去除其中的重复项,并保留原始顺序。 ```python def remove_duplicates(lst): seen = set() result = [] for item in lst: if item not in seen: seen.add(item) result.append(item) return result input_list = [1, 2, 3, 2, 4, 5, 1] print(remove_duplicates(input_list)) # 输出:[1, 2, 3, 4, 5] ``` ##### 题目 2: 找到两个列表的不同部分 已知两个列表分别为 `list_a = [1, 2, 3, 4]` 和 `list_b = [3, 4, 5, 6]`,找出它们之间的差异。 ```python list_a = [1, 2, 3, 4] list_b = [3, 4, 5, 6] diff_a = [item for item in list_a if item not in list_b] diff_b = [item for item in list_b if item not in list_a] print(diff_a) # 输出:[1, 2] print(diff_b) # 输出:[5, 6] ``` ##### 题目 3: 计算子序列的最大和 对于任意长度的整数列表(可能包含负数),找到其连续子序列的最大和。 ```python def max_subarray_sum(nums): current_max = global_max = nums[0] for num in nums[1:]: current_max = max(num, current_max + num) global_max = max(global_max, current_max) return global_max example_list = [-2, 1, -3, 4, -1, 2, 1, -5, 4] print(max_subarray_sum(example_list)) # 输出:6 (最大子序列为 [4, -1, 2, 1]) ``` ##### 题目 4: 合并多个有序列表 假设存在若干个已经按升序排列的小型列表,将其合并成一个新的整体有序列表。 ```python import heapq lists = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] merged_list = list(heapq.merge(*lists)) print(merged_list) # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9] ``` --- ### 总结 上述练习涵盖了列表的基本操作、高级技巧及其与其他模块的结合应用。这些例子不仅有助于理解列表的核心功能,还能提升解决复杂问题的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值