【记录】Rust|Rust对比Python的语法学习(Vec、VecDeque)
本文正文内容由Gemini生成,大体上应无错处,但未细致核对,若有问题欢迎指出。
✍️ 【记录】Rust|Rust对比Python的语法学习(Vec、VecDeque)
文章目录
作为一名经验丰富的 Python 开发者,在转向 Rust 时,最开始接触到的数据结构常常让人联想到 Python 中熟悉的列表(
list)。然而,Rust 提供了更细致、性能更优化的集合类型。本文将聚焦于 Rust 中两个核心的可变序列容器: Vec<T> 和 VecDeque<T>,并对比它们在 Python 中最接近的对应物。
1. 🐍 Python 的序列基础:list 和 collections.deque
在 Python 中,我们通常使用 list 来处理大多数有序集合的需求。
-
list(列表): 这是 Python 的“万能”序列。它在内部实现为动态数组,因此:- 快速访问 (O(1)):通过索引访问元素非常快。
- 快速尾部操作 (O(1) 均摊):在末尾添加 (
append) 或移除 (pop) 元素通常很快。 - 慢速头部/中间操作 (O(n)):在列表开头或中间插入或删除元素需要移动后续所有元素,效率低下。
-
collections.deque(双端队列): 当我们需要在序列两端高效地操作元素时,我们会使用deque。它在内部实现为双向链表,因此:- 快速头部/尾部操作 (O(1)):在开头 (
appendleft) 或末尾 (append) 操作元素都非常快。 - 慢速中间访问 (O(n)):通过索引访问中间元素效率较低。
- 快速头部/尾部操作 (O(1)):在开头 (
2. 🦀 Rust 的动态序列:Vec<T>
Rust 的 std::vec::Vec<T> 是 Rust 语言中最核心、最常用的动态数组类型。
Rust: Vec<T> |
Python 对比 | 核心特点 |
|---|---|---|
Vec<T> (Vector) |
list (列表) |
动态数组,存储在堆上。 |
| 添加/删除 | push/pop |
快速尾部操作 O(1) 均摊。 |
| 访问/修改 | vec[i] |
快速随机访问 O(1)。 |
| 头部操作 | insert(0, ...) / remove(0) |
慢速头部/中间操作 O(n)。 |
📢 关键差异:Vec<T> 的行为几乎与 Python 的 list 完全一致。它是连续存储在内存中的,这使得它具有极高的数据局部性和快速的随机访问。在 Rust 中,如果您的主要操作是遍历、通过索引访问和在末尾添加/移除,请始终选择 Vec<T>。
示例 (Rust):
let mut my_vec = Vec::new(); // 创建一个空的 Vec
my_vec.push(10); // O(1) 均摊:在末尾添加
my_vec.push(20);
println!("第一个元素: {}", my_vec[0]); // O(1):快速随机访问
my_vec.insert(0, 5); // O(n):在开头插入,性能开销大
// my_vec 现在是 [5, 10, 20]
3. 🦀 Rust 的双端队列:VecDeque<T>
Rust 的 std::collections::VecDeque<T> 是一个双端队列,但它的实现方式与 Python 的 deque 大不相同。
Rust: VecDeque<T> |
Python 对比 | 核心特点 |
|---|---|---|
VecDeque<T> (Vector Deque) |
collections.deque |
环形缓冲区 (Circular Buffer) 实现的双端队列。 |
| 添加/删除 | push_front/pop_front |
快速头部/尾部操作 O(1) 均摊。 |
| 访问/修改 | deque[i] |
比 Vec 慢,但比 Python 的 deque 快 (O(1))。 |
| 中间操作 | insert(i, ...) |
慢速中间操作 O(n)。 |
📢 关键差异:
Python 的 deque 使用双向链表,随机访问很慢 (O(n))。而 Rust 的 VecDeque<T> 使用环形缓冲区(本质上是一种循环使用的数组)。
- Rust 的优势: 环形缓冲区结构让
VecDeque<T>仍然保留了快速的随机访问 (O(1)),尽管常数因子比Vec<T>稍大,但远胜于链表实现的 O(n)。 - 使用场景: 当您需要高效地处理队列(Queue)或栈(Stack)的行为,并且需要在两端进行频繁操作时,
VecDeque<T>是首选。
示例 (Rust):
use std::collections::VecDeque;
let mut my_deque = VecDeque::new();
my_deque.push_back(10); // O(1) 均摊:在末尾添加
my_deque.push_front(5); // O(1) 均摊:在开头添加
// my_deque 现在是 [5, 10]
let first = my_deque.pop_front(); // O(1) 均摊:移除开头元素
// first 是 Some(5)
println!("剩余元素: {:?}", my_deque);
// 随机访问仍然很快,是 O(1)
println!("剩余第一个元素: {}", my_deque[0]);
总结对比
| 特性 | Python list |
Python collections.deque |
Rust Vec<T> |
Rust VecDeque<T> |
|---|---|---|---|---|
| 底层实现 | 动态数组 | 双向链表 | 动态数组 | 环形缓冲区 |
| 随机访问 (O(1) vs O(n)) | O(1) | O(n) | O(1) | O(1) |
| 尾部操作 | O(1) 均摊 | O(1) | O(1) 均摊 | O(1) 均摊 |
| 头部操作 | O(n) | O(1) | O(n) | O(1) 均摊 |
| 推荐用途 | 通用序列 | 队列/双端队列 | 通用序列,高性能访问 | 队列/栈,双端高效操作 |
🚀 结论与建议
作为从 Python 转来的开发者,您的选择指南如下:
-
优先使用
Vec<T>: 除非您有明确的理由需要高性能的头部操作,否则在 Rust 中,Vec<T>才是您的默认序列类型,因为它带来了最佳的随机访问性能和数据局部性。它完全等同于您在 Python 中使用list的习惯。 -
需要双端操作时选择
VecDeque<T>: 当您需要实现一个高效的队列(FIFO)或栈(LIFO,且不需要只操作末端),并且需要频繁在两端push/pop时,VecDeque<T>才是正确的选择。
Rust 通过提供这些细分的集合类型,让开发者可以根据实际的性能需求进行精确的选择,从而构建出更高效的应用。
本账号所有文章均为原创,欢迎转载,请注明文章出处:https://shandianchengzi.blog.csdn.net/article/details/154980165。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。
更多推荐
所有评论(0)