Vec 动态数组
学习目标
- 创建和初始化 Vec
- 掌握增删改查操作
- 理解所有权和借用规则
- 掌握迭代器和常用方法
核心概念
创建 Vec
fn main() {
let v1: Vec<i32> = Vec::new(); // 空 Vec
let v2 = vec![1, 2, 3]; // 宏创建
let v3 = vec![0; 10]; // 10 个 0
let v4 = Vec::with_capacity(100); // 预分配容量
}
增删改查
fn main() {
let mut v = vec![1, 2, 3];
// 增
v.push(4); // 尾部追加
v.insert(0, 0); // 指定位置插入
v.extend([5, 6, 7]); // 批量追加
// 删
v.pop(); // 移除并返回最后一个
v.remove(0); // 移除指定索引
v.retain(|&x| x > 2); // 保留满足条件的
v.clear(); // 清空
// 改
let mut v = vec![1, 2, 3];
v[0] = 10; // 通过索引修改
// 查
let first = v[0]; // 索引访问(越界 panic)
let safe = v.get(0); // 安全访问(返回 Option)
let len = v.len();
let is_empty = v.is_empty();
let contains = v.contains(&2);
}
所有权
fn main() {
let mut v = vec![String::from("hello"), String::from("world")];
// ❌ 移动出 Vec
// let first = v[0]; // 编译错误:不能移出借用
// ✅ 借用
let first = &v[0];
println!("{}", first);
// ✅ 克隆
let first = v[0].clone();
// ✅ swap_remove(移出并用最后一个填补)
let first = v.swap_remove(0);
println!("{}", first); // "hello",v 变成 ["world"]
}
迭代
fn main() {
let v = vec![1, 2, 3, 4, 5];
// 不可变迭代
for val in &v {
println!("{}", val);
}
// 可变迭代
let mut v = vec![1, 2, 3];
for val in &mut v {
*val *= 2;
}
// 消耗性迭代(迭代后 v 不可用)
let v = vec![1, 2, 3];
for val in v {
println!("{}", val);
}
// println!("{:?}", v); // ❌ 已移动
}
常用方法
fn main() {
let mut v = vec![3, 1, 4, 1, 5, 9, 2, 6];
// 排序
v.sort(); // 升序
v.sort_by(|a, b| b.cmp(a)); // 降序
v.sort_unstable(); // 不稳定排序(更快)
// 去重(需先排序)
v.sort();
v.dedup();
// 切片
let slice = &v[1..4];
let (left, right) = v.split_at(3);
// 窗口和块
for window in v.windows(3) {
println!("{:?}", window); // 滑动窗口
}
for chunk in v.chunks(2) {
println!("{:?}", chunk); // 固定大小块
}
// 连接
let v = vec![1, 2, 3];
let sum: i32 = v.iter().sum();
let product: i32 = v.iter().product();
let max = v.iter().max();
let min = v.iter().min();
}
二维 Vec
fn main() {
// 创建 3x4 矩阵
let mut matrix = vec![vec![0; 4]; 3];
matrix[1][2] = 42;
println!("{:?}", matrix);
// 遍历
for (i, row) in matrix.iter().enumerate() {
for (j, &val) in row.iter().enumerate() {
print!("{:4}", val);
}
println!();
}
}
实践练习
练习 1:去重保序
fn dedup_ordered<T: PartialEq>(v: &mut Vec<T>) {
let mut i = 0;
while i < v.len() {
let mut j = i + 1;
while j < v.len() {
if v[i] == v[j] {
v.remove(j);
} else {
j += 1;
}
}
i += 1;
}
}
fn main() {
let mut v = vec![1, 3, 2, 3, 1, 4, 2];
dedup_ordered(&mut v);
println!("{:?}", v); // [1, 3, 2, 4]
}
练习 2:矩阵转置
fn transpose(matrix: &Vec<Vec<i32>>) -> Vec<Vec<i32>> {
let rows = matrix.len();
let cols = matrix[0].len();
let mut result = vec![vec![0; rows]; cols];
for i in 0..rows {
for j in 0..cols {
result[j][i] = matrix[i][j];
}
}
result
}
fn main() {
let m = vec![
vec![1, 2, 3],
vec![4, 5, 6],
];
let t = transpose(&m);
println!("{:?}", t); // [[1, 4], [2, 5], [3, 6]]
}
练习 3:滑动窗口最大值
fn max_sliding_window(v: &[i32], k: usize) -> Vec<i32> {
v.windows(k).map(|w| *w.iter().max().unwrap()).collect()
}
fn main() {
let data = vec![1, 3, -1, -3, 5, 3, 6, 7];
let result = max_sliding_window(&data, 3);
println!("{:?}", result); // [3, 3, 5, 5, 6, 7]
}
常见错误
1. 越界访问
let v = vec![1, 2, 3];
// let x = v[10]; // ❌ panic: index out of bounds
let x = v.get(10); // ✅ 返回 None
2. 迭代时修改
let mut v = vec![1, 2, 3];
// for val in &v {
// v.push(*val); // ❌ 不能在不可变借用期间可变借用
// }
3. 移动出 Vec
let v = vec![String::from("hello")];
// let s = v[0]; // ❌ 不能移出借用
let s = v.into_iter().next().unwrap(); // ✅ 消耗性迭代
小结
| 操作 | 语法 |
|---|---|
| 创建 | vec![...], Vec::new() |
| 追加 | push, extend |
| 访问 | v[i], v.get(i) |
| 迭代 | for x in &v |
| 排序 | sort, sort_by |
| 过滤 | retain, iter().filter() |
练习编辑器
rust
Loading...