Vector - Container động linh hoạt
📖 Giới thiệu
Vector là container động trong STL, tương tự như mảng nhưng có thể thay đổi kích thước tự động. Vector lưu trữ các phần tử liên tiếp trong bộ nhớ và cung cấp truy cập ngẫu nhiên nhanh chóng.
Ví dụ đơn giản đầu tiên
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Tạo vector rỗng
vector<int> numbers;
// Thêm phần tử
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// Hiển thị
cout << "Vector có " << numbers.size() << " phần tử: ";
for (int num : numbers) {
cout << num << " ";
}
cout << endl;
// Truy cập phần tử
cout << "Phần tử đầu: " << numbers[0] << endl;
cout << "Phần tử cuối: " << numbers.back() << endl;
return 0;
}🔧 Cú pháp
Khai báo Vector
cpp
#include <vector>
vector<int> int_vector; // Vector rỗng
vector<int> sized_vector(5); // 5 phần tử mặc định (0)
vector<int> init_vector(5, 10); // 5 phần tử, giá trị 10
vector<int> copy_vector{1, 2, 3, 4, 5}; // Khởi tạo với list
vector<int> from_array(arr, arr + size); // Từ mảngCác phương thức cơ bản
cpp
// Thêm/xóa phần tử
vector.push_back(value); // Thêm cuối
vector.pop_back(); // Xóa cuối
vector.insert(iterator, value); // Chèn tại vị trí
vector.erase(iterator); // Xóa tại vị trí
// Truy cập
vector[index]; // Truy cập trực tiếp
vector.at(index); // Truy cập an toàn
vector.front(); // Phần tử đầu
vector.back(); // Phần tử cuối
// Thông tin
vector.size(); // Số phần tử
vector.capacity(); // Dung lượng hiện tại
vector.empty(); // Kiểm tra rỗng
vector.clear(); // Xóa tất cả🔬 Phân tích & Giải thích
Vector vs Array
Vector:
- Kích thước động
- Tự động quản lý bộ nhớ
- Nhiều phương thức hữu ích
- Overhead nhỏ
Array:
- Kích thước cố định
- Quản lý bộ nhớ thủ công
- Ít tính năng
- Hiệu suất cao hơn một chút
Memory Management trong Vector
cpp
vector<int> v;
cout << "Capacity: " << v.capacity() << ", Size: " << v.size() << endl;
for (int i = 0; i < 10; i++) {
v.push_back(i);
cout << "After push " << i << " - Capacity: " << v.capacity()
<< ", Size: " << v.size() << endl;
}💻 Ví dụ minh họa
Ví dụ 1: Quản lý danh sách sinh viên
cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
struct SinhVien {
string ten;
int tuoi;
double diem;
SinhVien(string t, int tuoi_sv, double d) : ten(t), tuoi(tuoi_sv), diem(d) {}
void hien_thi() const {
cout << setw(15) << ten << setw(5) << tuoi << setw(8) << fixed << setprecision(1) << diem << endl;
}
};
class QuanLySinhVien {
private:
vector<SinhVien> danh_sach;
public:
void them_sinh_vien(const string& ten, int tuoi, double diem) {
danh_sach.emplace_back(ten, tuoi, diem);
cout << "✅ Đã thêm sinh viên: " << ten << endl;
}
void xoa_sinh_vien(const string& ten) {
auto it = find_if(danh_sach.begin(), danh_sach.end(),
[&ten](const SinhVien& sv) { return sv.ten == ten; });
if (it != danh_sach.end()) {
danh_sach.erase(it);
cout << "✅ Đã xóa sinh viên: " << ten << endl;
} else {
cout << "❌ Không tìm thấy sinh viên: " << ten << endl;
}
}
void tim_sinh_vien(const string& ten) {
auto it = find_if(danh_sach.begin(), danh_sach.end(),
[&ten](const SinhVien& sv) { return sv.ten == ten; });
if (it != danh_sach.end()) {
cout << "🔍 Tìm thấy sinh viên:" << endl;
cout << setw(15) << "Tên" << setw(5) << "Tuổi" << setw(8) << "Điểm" << endl;
cout << string(28, '-') << endl;
it->hien_thi();
} else {
cout << "❌ Không tìm thấy sinh viên: " << ten << endl;
}
}
void hien_thi_tat_ca() {
if (danh_sach.empty()) {
cout << "📋 Danh sách sinh viên trống!" << endl;
return;
}
cout << "\n📋 DANH SÁCH SINH VIÊN (" << danh_sach.size() << " sinh viên)" << endl;
cout << setw(15) << "Tên" << setw(5) << "Tuổi" << setw(8) << "Điểm" << endl;
cout << string(28, '-') << endl;
for (const auto& sv : danh_sach) {
sv.hien_thi();
}
cout << string(28, '-') << endl;
}
void sap_xep_theo_diem() {
sort(danh_sach.begin(), danh_sach.end(),
[](const SinhVien& a, const SinhVien& b) {
return a.diem > b.diem; // Giảm dần
});
cout << "✅ Đã sắp xếp theo điểm (cao → thấp)" << endl;
}
void sap_xep_theo_ten() {
sort(danh_sach.begin(), danh_sach.end(),
[](const SinhVien& a, const SinhVien& b) {
return a.ten < b.ten; // A → Z
});
cout << "✅ Đã sắp xếp theo tên (A → Z)" << endl;
}
void thong_ke() {
if (danh_sach.empty()) {
cout << "📊 Không có dữ liệu để thống kê!" << endl;
return;
}
double tong_diem = 0;
double diem_cao_nhat = danh_sach[0].diem;
double diem_thap_nhat = danh_sach[0].diem;
int so_sv_gioi = 0, so_sv_kha = 0, so_sv_tb = 0, so_sv_yeu = 0;
for (const auto& sv : danh_sach) {
tong_diem += sv.diem;
diem_cao_nhat = max(diem_cao_nhat, sv.diem);
diem_thap_nhat = min(diem_thap_nhat, sv.diem);
if (sv.diem >= 8.0) so_sv_gioi++;
else if (sv.diem >= 6.5) so_sv_kha++;
else if (sv.diem >= 5.0) so_sv_tb++;
else so_sv_yeu++;
}
cout << "\n📊 THỐNG KÊ" << endl;
cout << "Tổng số sinh viên: " << danh_sach.size() << endl;
cout << "Điểm trung bình: " << fixed << setprecision(2) << (tong_diem / danh_sach.size()) << endl;
cout << "Điểm cao nhất: " << diem_cao_nhat << endl;
cout << "Điểm thấp nhất: " << diem_thap_nhat << endl;
cout << "Phân loại:" << endl;
cout << " - Giỏi (≥8.0): " << so_sv_gioi << " sinh viên" << endl;
cout << " - Khá (6.5-7.9): " << so_sv_kha << " sinh viên" << endl;
cout << " - Trung bình (5.0-6.4): " << so_sv_tb << " sinh viên" << endl;
cout << " - Yếu (<5.0): " << so_sv_yeu << " sinh viên" << endl;
}
vector<SinhVien> loc_theo_diem(double diem_toi_thieu) {
vector<SinhVien> ket_qua;
copy_if(danh_sach.begin(), danh_sach.end(), back_inserter(ket_qua),
[diem_toi_thieu](const SinhVien& sv) {
return sv.diem >= diem_toi_thieu;
});
cout << "🔍 Tìm thấy " << ket_qua.size() << " sinh viên có điểm ≥ " << diem_toi_thieu << endl;
return ket_qua;
}
size_t kich_thuoc() const {
return danh_sach.size();
}
};
int main() {
cout << "=== HỆ THỐNG QUẢN LÝ SINH VIÊN ===" << endl;
QuanLySinhVien ql;
// Thêm sinh viên
cout << "\n--- Thêm sinh viên ---" << endl;
ql.them_sinh_vien("Nguyễn Văn A", 20, 8.5);
ql.them_sinh_vien("Trần Thị B", 19, 7.2);
ql.them_sinh_vien("Lê Văn C", 21, 9.1);
ql.them_sinh_vien("Phạm Thị D", 20, 6.8);
ql.them_sinh_vien("Hoàng Văn E", 22, 4.5);
// Hiển thị danh sách
ql.hien_thi_tat_ca();
// Thống kê
ql.thong_ke();
// Sắp xếp theo điểm
cout << "\n--- Sắp xếp theo điểm ---" << endl;
ql.sap_xep_theo_diem();
ql.hien_thi_tat_ca();
// Sắp xếp theo tên
cout << "\n--- Sắp xếp theo tên ---" << endl;
ql.sap_xep_theo_ten();
ql.hien_thi_tat_ca();
// Tìm kiếm
cout << "\n--- Tìm kiếm ---" << endl;
ql.tim_sinh_vien("Lê Văn C");
ql.tim_sinh_vien("Nguyễn Văn X");
// Lọc sinh viên giỏi
cout << "\n--- Lọc sinh viên giỏi ---" << endl;
auto sv_gioi = ql.loc_theo_diem(8.0);
if (!sv_gioi.empty()) {
cout << "Danh sách sinh viên giỏi:" << endl;
cout << setw(15) << "Tên" << setw(5) << "Tuổi" << setw(8) << "Điểm" << endl;
cout << string(28, '-') << endl;
for (const auto& sv : sv_gioi) {
sv.hien_thi();
}
}
// Xóa sinh viên
cout << "\n--- Xóa sinh viên ---" << endl;
ql.xoa_sinh_vien("Hoàng Văn E");
ql.hien_thi_tat_ca();
return 0;
}Ví dụ 2: Vector 2D và ma trận
cpp
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
class Matrix {
private:
vector<vector<int>> data;
int rows, cols;
public:
Matrix(int r, int c) : rows(r), cols(c) {
data.resize(rows, vector<int>(cols, 0));
cout << "Tạo ma trận " << rows << "x" << cols << endl;
}
Matrix(const vector<vector<int>>& init_data) {
data = init_data;
rows = data.size();
cols = rows > 0 ? data[0].size() : 0;
cout << "Tạo ma trận từ dữ liệu sẵn có " << rows << "x" << cols << endl;
}
void nhap_du_lieu() {
cout << "Nhập dữ liệu cho ma trận " << rows << "x" << cols << ":" << endl;
for (int i = 0; i < rows; i++) {
cout << "Dòng " << (i + 1) << ": ";
for (int j = 0; j < cols; j++) {
cin >> data[i][j];
}
}
}
void nhap_ngau_nhien(int min_val = 1, int max_val = 10) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
data[i][j] = min_val + rand() % (max_val - min_val + 1);
}
}
cout << "Đã điền ma trận với số ngẫu nhiên (" << min_val << "-" << max_val << ")" << endl;
}
void hien_thi() const {
cout << "\nMa trận " << rows << "x" << cols << ":" << endl;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout << setw(4) << data[i][j];
}
cout << endl;
}
cout << endl;
}
Matrix cong(const Matrix& other) const {
if (rows != other.rows || cols != other.cols) {
throw invalid_argument("Kích thước ma trận không khớp để cộng!");
}
Matrix result(rows, cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result.data[i][j] = data[i][j] + other.data[i][j];
}
}
cout << "Đã thực hiện phép cộng ma trận" << endl;
return result;
}
Matrix nhan(const Matrix& other) const {
if (cols != other.rows) {
throw invalid_argument("Không thể nhân ma trận: số cột của ma trận 1 ≠ số dòng của ma trận 2!");
}
Matrix result(rows, other.cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < other.cols; j++) {
for (int k = 0; k < cols; k++) {
result.data[i][j] += data[i][k] * other.data[k][j];
}
}
}
cout << "Đã thực hiện phép nhân ma trận" << endl;
return result;
}
Matrix chuyen_vi() const {
Matrix result(cols, rows);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result.data[j][i] = data[i][j];
}
}
cout << "Đã thực hiện chuyển vị ma trận" << endl;
return result;
}
void nhan_voi_so(int scalar) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
data[i][j] *= scalar;
}
}
cout << "Đã nhân ma trận với số " << scalar << endl;
}
vector<int> tim_max_moi_dong() const {
vector<int> max_values;
for (int i = 0; i < rows; i++) {
int max_val = data[i][0];
for (int j = 1; j < cols; j++) {
max_val = max(max_val, data[i][j]);
}
max_values.push_back(max_val);
}
return max_values;
}
vector<int> tim_min_moi_cot() const {
vector<int> min_values;
for (int j = 0; j < cols; j++) {
int min_val = data[0][j];
for (int i = 1; i < rows; i++) {
min_val = min(min_val, data[i][j]);
}
min_values.push_back(min_val);
}
return min_values;
}
int tinh_tong() const {
int sum = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
sum += data[i][j];
}
}
return sum;
}
double tinh_trung_binh() const {
return static_cast<double>(tinh_tong()) / (rows * cols);
}
int get_rows() const { return rows; }
int get_cols() const { return cols; }
};
void demo_matrix_operations() {
cout << "=== DEMO OPERATIONS VỚI MA TRẬN ===" << endl;
srand(time(0)); // Seed for random numbers
// Tạo ma trận
cout << "\n--- Tạo ma trận ---" << endl;
Matrix ma_tran_A(3, 3);
Matrix ma_tran_B(3, 3);
ma_tran_A.nhap_ngau_nhien(1, 5);
ma_tran_B.nhap_ngau_nhien(1, 5);
cout << "Ma trận A:";
ma_tran_A.hien_thi();
cout << "Ma trận B:";
ma_tran_B.hien_thi();
// Phép cộng
cout << "\n--- Phép cộng A + B ---" << endl;
try {
Matrix tong = ma_tran_A.cong(ma_tran_B);
cout << "Kết quả A + B:";
tong.hien_thi();
} catch (const exception& e) {
cout << "Lỗi: " << e.what() << endl;
}
// Phép nhân
cout << "\n--- Phép nhân A × B ---" << endl;
try {
Matrix tich = ma_tran_A.nhan(ma_tran_B);
cout << "Kết quả A × B:";
tich.hien_thi();
} catch (const exception& e) {
cout << "Lỗi: " << e.what() << endl;
}
// Chuyển vị
cout << "\n--- Chuyển vị ma trận A ---" << endl;
Matrix chuyen_vi_A = ma_tran_A.chuyen_vi();
cout << "Chuyển vị của A:";
chuyen_vi_A.hien_thi();
// Nhân với scalar
cout << "\n--- Nhân A với số 3 ---" << endl;
Matrix ma_tran_A_copy = ma_tran_A; // Copy for demo
ma_tran_A_copy.nhan_voi_so(3);
cout << "A × 3:";
ma_tran_A_copy.hien_thi();
// Phân tích ma trận
cout << "\n--- Phân tích ma trận A ---" << endl;
vector<int> max_dong = ma_tran_A.tim_max_moi_dong();
vector<int> min_cot = ma_tran_A.tim_min_moi_cot();
cout << "Max mỗi dòng: ";
for (int i = 0; i < max_dong.size(); i++) {
cout << "Dòng " << (i+1) << ": " << max_dong[i] << " ";
}
cout << endl;
cout << "Min mỗi cột: ";
for (int j = 0; j < min_cot.size(); j++) {
cout << "Cột " << (j+1) << ": " << min_cot[j] << " ";
}
cout << endl;
cout << "Tổng tất cả phần tử: " << ma_tran_A.tinh_tong() << endl;
cout << "Giá trị trung bình: " << fixed << setprecision(2) << ma_tran_A.tinh_trung_binh() << endl;
}
int main() {
demo_matrix_operations();
return 0;
}🏋️ Thực hành
Bài tập 1: Quản lý kho hàng
Tạo class KhoHang sử dụng vector<SanPham> với:
- Thêm, xóa, sửa sản phẩm
- Tìm kiếm theo tên, loại
- Sắp xếp theo giá, số lượng
Bài tập 2: Vector calculator
Tạo class VectorCalculator với:
- Các phép toán vector: cộng, trừ, nhân scalar
- Tích vô hướng, độ dài vector
- Góc giữa hai vector
Bài tập 3: Game inventory
Tạo hệ thống inventory cho game với:
vector<Item>lưu đồ vật- Sorting theo giá trị, rarity
- Filtering theo loại item
📋 Tóm tắt
Vector: Container động, tự động thay đổi kích thước
Ưu điểm:
- Truy cập ngẫu nhiên O(1)
- Thêm/xóa cuối O(1) amortized
- Cache-friendly (phần tử liên tiếp)
- Nhiều algoritm STL hỗ trợ
Nhược điểm:
- Chèn/xóa giữa O(n)
- Có thể reallocate khi hết capacity
Khi nào dùng:
- Cần truy cập ngẫu nhiên
- Thường thêm/xóa ở cuối
- Cần tương thích với C arrays
Bài tiếp theo: List - Tìm hiểu về linked list và insertion/deletion hiệu quả.