第一篇:Python 进阶-高级数据结构

第一篇:Python 进阶-高级数据结构

1. 堆(Heap)数据结构

堆的概念与原理

堆是一种特殊的树形数据结构,它通常满足以下两个性质:

  • 结构性:堆是一棵完全二叉树,即除了最后一层外,每一层的节点数都是满的,并且最后一层的节点都靠左排列。
  • 堆序性:分为两种类型,最大堆和最小堆。在最大堆中,每个节点的值都大于或等于其左右子节点的值;在最小堆中,每个节点的值都小于或等于其左右子节点的值。

堆常用于实现优先队列,优先队列是一种特殊的队列,每次从队列中取出的元素是具有最高优先级的元素。在最大堆实现的优先队列中,最大元素具有最高优先级;在最小堆实现的优先队列中,最小元素具有最高优先级。堆的主要操作包括插入元素和删除堆顶元素(最大堆为最大值,最小堆为最小值)。这些操作的时间复杂度为 ( O(\log n) ),其中 ( n ) 是堆中元素的个数。这是因为堆的高度为 ( \log n ),插入和删除操作主要在堆的路径上进行调整,路径长度与堆的高度相关。

Python 中 heapq 模块的使用

Python 的 heapq 模块提供了堆数据结构的实现,默认实现的是最小堆。以下是一些常见的用法:

创建堆

可以将一个列表转换为堆结构,或者逐步向堆中添加元素。

import heapq

# 将列表转换为堆
nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
heapq.heapify(nums)
print(list(nums))  # 输出: [1, 1, 2, 3, 3, 9, 4, 6, 5, 5, 5]

heapq.heapify() 函数会将传入的列表原地转换为堆结构。

插入元素

使用 heapq.heappush() 函数向堆中插入元素。

import heapq

heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 3)
heapq.heappush(heap, 7)
heapq.heappush(heap, 1)
print(list(heap))  # 输出: [1, 3, 7, 5]
获取并删除堆顶元素

使用 heapq.heappop() 函数获取并删除堆顶元素(即最小值)。

import heapq

heap = [1, 3, 7, 5]
smallest = heapq.heappop(heap)
print(smallest)  # 输出: 1
print(list(heap))  # 输出: [3, 5, 7]
获取堆中最小的 ( k ) 个元素

使用 heapq.nsmallest() 函数可以获取堆中最小的 ( k ) 个元素。

import heapq

nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
smallest_three = heapq.nsmallest(3, nums)
print(smallest_three)  # 输出: [1, 1, 2]

2. 双端队列(Deque)

双端队列的特点

双端队列(Deque,即 Double-ended Queue 的缩写)是一种特殊的队列数据结构,它允许在队列的两端进行插入和删除操作。与普通队列(只允许在一端插入,另一端删除)相比,双端队列具有更高的灵活性。其主要特点包括:

  • 两端操作:可以在队列的头部和尾部执行添加和移除元素的操作,这使得双端队列在某些场景下比普通队列和栈更适用,例如实现一个支持先进先出(FIFO)和后进先出(LIFO)操作的数据结构。
  • 高效性:在双端队列的两端进行插入和删除操作的时间复杂度均为 ( O(1) ),而在列表的头部插入或删除元素的时间复杂度为 ( O(n) ),因为列表需要移动元素来腾出空间或填补空缺。

collections.deque 的操作方法

Python 的 collections 模块提供了 deque 类来实现双端队列。以下是一些常用的操作方法:

创建双端队列
from collections import deque

# 创建一个空的双端队列
dq = deque()

# 创建一个带有初始元素的双端队列
dq = deque([1, 2, 3])
在两端添加元素
  • append(x):在队列尾部添加元素 ( x )。
  • appendleft(x):在队列头部添加元素 ( x )。
from collections import deque

dq = deque()
dq.append(1)
dq.appendleft(2)
print(dq)  # 输出: deque([2, 1])
在两端删除元素
  • pop():移除并返回队列尾部的元素。
  • popleft():移除并返回队列头部的元素。
from collections import deque

dq = deque([1, 2, 3])
tail = dq.pop()
head = dq.popleft()
print(tail)  # 输出: 3
print(head)  # 输出: 1
print(dq)  # 输出: deque([2])
访问元素

可以像列表一样通过索引访问双端队列中的元素,但由于双端队列的实现并非基于连续内存,随机访问的效率较低,时间复杂度为 ( O(n) )。

from collections import deque

dq = deque([1, 2, 3])
print(dq[1])  # 输出: 2
限制双端队列的大小

可以在创建双端队列时指定最大长度,当双端队列达到最大长度时,再添加元素会导致另一端的元素被自动移除。

from collections import deque

dq = deque(maxlen = 3)
dq.append(1)
dq.append(2)
dq.append(3)
dq.append(4)
print(dq)  # 输出: deque([2, 3, 4])

通过学习堆和双端队列这两种高级数据结构及其在 Python 中的实现,你可以更高效地解决各种编程问题,尤其是涉及到优先队列和灵活数据操作的场景。如果在学习过程中有任何疑问,欢迎随时提问。同时,点赞、收藏并关注,获取更多 Python 进阶知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员勇哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值