Vec详解
> Vec是可增长的动态数组,数据存储在堆上。掌握Vec的创建、容量管理和常用操作方法。
Vec(可增长向量)详解
什么是 Vec?
Vec(Vector)是 Rust 标准库提供的可增长数组:
┌─────────────────────────────────────────┐
│ Vec 的内部结构 │
├─────────────────────────────────────────┤
│ │
│ 栈(Stack) │
│ ┌───────────┬───────────┬─────────┐ │
│ │ 指针 │ 长度 │ 容量 │ │
│ │ (指向堆) │ (元素数) │ (空间) │ │
│ └─────┬─────┴─────┬─────┴────┬────┘ │
│ │ │ │ │
│ ▼ │ │ │
│ 堆(Heap) │ │ │
│ ┌─────────────────┘ │ │
│ │ ┌─────┬─────┬─────┬─────┐ │ │
│ │ │ 1 │ 2 │ 3 │ 4 │ │ │
│ │ └─────┴─────┴─────┴─────┘ │ │
│ │ ←─── 已使用 (len=4) ───→ │ │
│ │ ←────── 容量 (cap=4) ─────→│ │
│ └────────────────────────────┘ │
│ │
│ 当 push 超过容量时: │
│ 1. 分配更大的新内存(通常 2 倍) │
│ 2. 复制所有元素到新内存 │
│ 3. 释放旧内存 │
│ │
└─────────────────────────────────────────┘创建 Vec 的多种方式
rust
▶ Runfn main() {
// 方式 1:使用 Vec::new()
let mut v1: Vec<i32> = Vec::new();
v1.push(1);
v1.push(2);
// 方式 2:使用 vec! 宏(最常用)
let v2 = vec![1, 2, 3, 4, 5];
let v3: Vec<i32> = vec![]; // 空 Vec
// 方式 3:预分配容量(性能优化)
let mut v4: Vec<i32> = Vec::with_capacity(100);
println!("容量:{}", v4.capacity()); // 100
for i in 0..50 {
v4.push(i); // 不会重新分配
}
println!("长度:{}, 容量:{}", v4.len(), v4.capacity());
// 方式 4:从迭代器创建
let v5: Vec<i32> = (1..=5).collect();
println!("从范围创建:{:?}", v5); // [1, 2, 3, 4, 5]
// 方式 5:重复元素
let v6 = vec![0; 10]; // [0, 0, 0, ...](10 个 0)
let v7 = vec![1, 2, 3].repeat(3); // [1, 2, 3, 1, 2, 3, 1, 2, 3]
// 方式 6:类型推断
let v8 = Vec::new(); // Vec<_>,需要类型标注
let v9: Vec<String> = Vec::new(); // 明确类型
}Vec 的容量管理
rust
▶ Runfn main() {
let mut v = Vec::with_capacity(4);
println!("初始 - len: {}, capacity: {}", v.len(), v.capacity());
v.push(1);
println!("push 1 个 - len: {}, capacity: {}", v.len(), v.capacity());
v.push(2);
v.push(3);
v.push(4);
println!("push 4 个 - len: {}, capacity: {}", v.len(), v.capacity());
// 超过容量,触发重新分配
v.push(5);
println!("push 5 个 - len: {}, capacity: {}", v.len(), v.capacity());
// 容量从 4 增长到 8(或其他值,取决于实现)
// 手动调整容量
v.reserve(20); // 确保至少有 20 的额外容量
println!("reserve 后 - capacity: {}", v.capacity());
v.shrink_to_fit(); // 减少容量到实际长度
println!("shrink 后 - len: {}, capacity: {}", v.len(), v.capacity());
}添加元素
rust
▶ Runfn main() {
let mut numbers = Vec::new();
// push - 在末尾添加单个元素
numbers.push(1);
numbers.push(2);
numbers.push(3);
println!("push 后:{:?}", numbers); // [1, 2, 3]
// insert - 在指定位置插入
numbers.insert(1, 99); // 在索引 1 插入 99
println!("insert 后:{:?}", numbers); // [1, 99, 2, 3]
// extend - 批量添加多个元素
numbers.extend([4, 5, 6]);
println!("extend 后:{:?}", numbers); // [1, 99, 2, 3, 4, 5, 6]
// 从另一个 Vec 添加
let more = vec![7, 8, 9];
numbers.extend(more);
println!("extend Vec 后:{:?}", numbers);
}访问和修改元素
rust
▶ Runfn main() {
let mut numbers = vec![10, 20, 30, 40, 50];
// 索引访问
let third = numbers[2]; // 30
println!("第三个元素:{}", third);
// 索引修改
numbers[0] = 100;
println!("修改后:{:?}", numbers); // [100, 20, 30, 40, 50]
// 安全访问(返回 Option)
match numbers.get(2) {
Some(value) => println!("索引 2: {}", value),
None => println!("索引不存在"),
}
// 获取首尾元素
println!("第一个:{:?}", numbers.first()); // Some(100)
println!("最后一个:{:?}", numbers.last()); // Some(50)
// 获取可变引用
if let Some(first) = numbers.first_mut() {
*first = 999;
}
println!("修改第一个后:{:?}", numbers); // [999, 20, 30, 40, 50]
}移除元素
rust
▶ Runfn main() {
let mut numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// pop - 移除并返回最后一个元素
let last = numbers.pop();
println!("pop 返回:{:?}", last); // Some(10)
println!("pop 后:{:?}", numbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
// remove - 移除指定位置的元素
let removed = numbers.remove(0);
println!("remove 返回:{}", removed); // 1
println!("remove 后:{:?}", numbers); // [2, 3, 4, 5, 6, 7, 8, 9]
// swap_remove - 移除并交换最后一个元素(O(1),不保持顺序)
let v = vec![1, 2, 3, 4, 5];
let removed = v.swap_remove(1); // 移除 2,用 5 填补
println!("swap_remove: {:?}, 移除:{}", v, removed); // [1, 5, 3, 4]
// truncate - 截断到指定长度
let mut v = vec![1, 2, 3, 4, 5];
v.truncate(2);
println!("truncate(2): {:?}", v); // [1, 2]
// clear - 清空所有元素
numbers.clear();
println!("clear 后:{:?}", numbers); // []
println!("clear 后长度:{}", numbers.len()); // 0
}Vec 常用方法大全
rust
▶ Runfn main() {
let mut v = vec![3, 1, 4, 1, 5, 9, 2, 6];
// ========== 查询方法 ==========
println!("长度:{}", v.len()); // 8
println!("容量:{}", v.capacity()); // >= 8
println!("是否为空:{}", v.is_empty()); // false
println!("包含 5: {}", v.contains(&5)); // true
println!("第一个:{:?}", v.first()); // Some(3)
println!("最后一个:{:?}", v.last()); // Some(6)
// ========== 修改方法 ==========
v.push(7); // 末尾添加
v.pop(); // 移除末尾
v.insert(0, 0); // 索引 0 插入 0
v.remove(0); // 移除索引 0
v[0] = 10; // 修改索引 0
// ========== 批量操作 ==========
v.extend([11, 12, 13]); // 批量添加
v.truncate(5); // 截断
v.clear(); // 清空
// ========== 排序 ==========
v = vec![3, 1, 4, 1, 5, 9, 2, 6];
v.sort(); // 原地排序
println!("排序后:{:?}", v); // [1, 1, 2, 3, 4, 5, 6, 9]
v.sort_by(|a, b| b.cmp(a)); // 降序排序
println!("降序:{:?}", v); // [9, 6, 5, 4, 3, 2, 1, 1]
v.reverse(); // 反转
println!("反转:{:?}", v); // [1, 1, 2, 3, 4, 5, 6, 9]
// ========== 查找 ==========
println!("3 的索引:{:?}", v.iter().position(|&x| x == 3)); // Some(3)
println!("是否有偶数:{}", v.iter().any(|&x| x % 2 == 0)); // true
println!("是否全为正:{}", v.iter().all(|&x| x > 0)); // true
// ========== 去重 ==========
v.sort();
v.dedup(); // 移除连续重复元素
println!("去重后:{:?}", v); // [1, 2, 3, 4, 5, 6, 9]
// ========== 迭代 ==========
for (i, val) in v.iter().enumerate() {
println!("v[{}] = {}", i, val);
}
}小结
- Vec<T>:可增长动态数组,堆上存储,指针+长度+容量三部分组成
- 创建:
vec![]宏最常用,Vec::with_capacity(n)预分配优化性能 - 增删改:
push()、pop()、insert()、remove()、extend() - 常用方法:
len()、capacity()、sort()、dedup()、迭代器等
练习题
详见:练习题