📦 Cấu Trúc Dữ Liệu
Từ điển các cấu trúc dữ liệu (data structures) trong Rust với giải thích dễ hiểu và ví dụ thực tế!
Tại Sao Quan Trọng?
Chọn đúng cấu trúc dữ liệu = Code nhanh hơn, dễ đọc hơn, ít bug hơn! 🚀
Collections - Bộ Sưu Tập
Array
Việt: Mảng cố định
ELI5: Như hộp trứng 10 quả - đúng 10 ô, không thêm không bớt! 🥚
Đặc điểm:
- ✅ Kích thước cố định
- ✅ Stack allocated (nhanh)
- ✅ Truy cập O(1)
- ❌ Không thể thay đổi size
fn main() {
// Khai báo: [type; size]
let numbers: [i32; 5] = [1, 2, 3, 4, 5];
// Khởi tạo giá trị giống nhau
let zeros = [0; 100]; // 100 số 0
// Truy cập
println!("Phần tử đầu: {}", numbers[0]);
println!("Độ dài: {}", numbers.len());
// Lặp qua array
for num in numbers.iter() {
println!("{}", num);
}
}
Khi nào dùng:
- ✅ Biết trước số lượng phần tử
- ✅ Cần performance cao
- ✅ Dữ liệu nhỏ, đơn giản
Vector (Vec<T>)
Việt: Mảng động
ELI5: Như chiếc ba lô ma thuật - bỏ thêm đồ vào được, lấy ra được! 🎒✨
Đặc điểm:
- ✅ Kích thước linh hoạt
- ✅ Heap allocated
- ✅ Có thể thêm/xóa phần tử
- ✅ Truy cập O(1)
fn main() {
// Cách tạo Vec
let mut v1: Vec<i32> = Vec::new();
let mut v2 = vec![1, 2, 3];
// Thêm phần tử
v1.push(10);
v1.push(20);
v1.push(30);
// Xóa phần tử cuối
let last = v1.pop(); // Some(30)
// Truy cập
let first = v1[0]; // Panic nếu out of bounds
let second = v1.get(1); // Option<&i32> - an toàn hơn
// Lặp
for num in &v1 {
println!("{}", num);
}
// Lặp và modify
for num in &mut v1 {
*num *= 2;
}
}
Methods hữu ích:
let mut v = vec![1, 2, 3];
v.len() // Độ dài: 3
v.is_empty() // false
v.contains(&2) // true
v.insert(0, 0) // Chèn 0 vào đầu
v.remove(1) // Xóa phần tử index 1
v.clear() // Xóa tất cả
Khi nào dùng:
- ✅ Không biết trước số lượng
- ✅ Cần thêm/xóa động
- ✅ List, stack, queue
Slice (&[T])
Việt: Lát cắt / View của array/vector
ELI5: Như xem 1 phần của bộ phim, không phải cả phim! 🎬👀
Đặc điểm:
- ✅ Reference đến một phần của array/vec
- ✅ Không own data
- ✅ Kích thước biết lúc runtime
fn main() {
let arr = [1, 2, 3, 4, 5];
// Tạo slices
let slice1 = &arr[1..4]; // [2, 3, 4]
let slice2 = &arr[..3]; // [1, 2, 3]
let slice3 = &arr[2..]; // [3, 4, 5]
let slice4 = &arr[..]; // [1, 2, 3, 4, 5]
print_slice(slice1);
}
fn print_slice(s: &[i32]) {
for item in s {
println!("{}", item);
}
}
HashMap (HashMap<K, V>)
Việt: Bảng băm / Từ điển
ELI5: Như danh bạ điện thoại - tra tên ra số điện thoại! 📱
Đặc điểm:
- ✅ Key-value pairs
- ✅ Truy cập nhanh O(1) trung bình
- ✅ Key phải implement
HashvàEq - ❌ Không có thứ tự
use std::collections::HashMap;
fn main() {
// Tạo HashMap
let mut scores = HashMap::new();
// Thêm data
scores.insert("Alice", 100);
scores.insert("Bob", 80);
scores.insert("Charlie", 95);
// Truy cập
match scores.get("Alice") {
Some(&score) => println!("Alice: {}", score),
None => println!("Không tìm thấy"),
}
// Hoặc dùng entry API
scores.entry("David").or_insert(70);
// Update giá trị
let score = scores.entry("Alice").or_insert(0);
*score += 10; // Alice giờ có 110
// Lặp qua HashMap
for (name, score) in &scores {
println!("{}: {}", name, score);
}
// Xóa
scores.remove("Bob");
}
Methods hữu ích:
let mut map = HashMap::new();
map.insert(key, value) // Thêm/cập nhật
map.get(&key) // Lấy giá trị: Option<&V>
map.contains_key(&key) // Kiểm tra tồn tại
map.remove(&key) // Xóa
map.len() // Số lượng entries
map.is_empty() // Kiểm tra rỗng
// Entry API - powerful!
map.entry(key).or_insert(default)
map.entry(key).and_modify(|v| *v += 1)
Khi nào dùng:
- ✅ Cần tra cứu nhanh bằng key
- ✅ Không quan tâm thứ tự
- ✅ Cache, database in-memory
HashSet (HashSet<T>)
Việt: Tập hợp / Set
ELI5: Như danh sách khách mời - mỗi người chỉ có tên 1 lần! 📝
Đặc điểm:
- ✅ Không có duplicate
- ✅ Kiểm tra tồn tại O(1)
- ✅ T phải implement
HashvàEq - ❌ Không có thứ tự
use std::collections::HashSet;
fn main() {
let mut set = HashSet::new();
// Thêm phần tử
set.insert(1);
set.insert(2);
set.insert(2); // Không thêm được (duplicate)
println!("Số phần tử: {}", set.len()); // 2
// Kiểm tra tồn tại
if set.contains(&1) {
println!("Có số 1");
}
// Set operations
let set1: HashSet<_> = [1, 2, 3].iter().collect();
let set2: HashSet<_> = [2, 3, 4].iter().collect();
let union: HashSet<_> = set1.union(&set2).collect();
let intersection: HashSet<_> = set1.intersection(&set2).collect();
let difference: HashSet<_> = set1.difference(&set2).collect();
}
Khi nào dùng: