Skip to content

C10: Vector nâng cao — Iterator, Resize, 2D Vector

Bạn sẽ học được: Iterator, resize/reserve, 2D vector, erase/insert
Yêu cầu: Đã học C04 (Mảng & Vector)
Thời gian: 45 phút


Iterator — Con trỏ vào vector

Analogies: Iterator = Ngón tay chỉ vào sách

flowchart LR
    A["begin()"] -->|"Ngón tay đầu"| B["end()"]
    B -->|"Ngón tay cuối + 1"| C["Kết thúc"]

Sử dụng Iterator

vector<int> a = {10, 20, 30, 40, 50};

// Iterator trỏ vào phần tử đầu
auto it = a.begin();
cout << *it << endl;  // 10

// Di chuyển iterator
it++;
cout << *it << endl;  // 20

it += 2;
cout << *it << endl;  // 40

// Iterator trỏ vào phần tử cuối + 1
auto itEnd = a.end();

Duyệt vector bằng iterator

vector<int> a = {10, 20, 30, 40, 50};

// Cách 1: Dùng iterator
for (auto it = a.begin(); it != a.end(); it++) {
    cout << *it << " ";
}

// Cách 2: Dùng range-based for (khuyến nghị)
for (int x : a) {
    cout << x << " ";
}

Resize & Reserve

Resize — Thay đổi kích thước

vector<int> a;

// Resize thành 5 phần tử (khởi tạo 0)
a.resize(5);
// a = {0, 0, 0, 0, 0}

// Resize thành 3 phần tử (cắt bớt)
a.resize(3);
// a = {0, 0, 0}

// Resize thành 7 phần tử, thêm giá trị 9
a.resize(7, 9);
// a = {0, 0, 0, 9, 9, 9, 9}

Reserve — Dự phòng bộ nhớ

1
2
3
4
5
6
7
8
9
vector<int> a;

// Dự phòng bộ nhớ cho 1000 phần tử
a.reserve(1000);

// Thêm 1000 phần tử (không phải cấp phát lại bộ nhớ)
for (int i = 0; i < 1000; i++) {
    a.push_back(i);
}

Khi nào dùng reserve?

  • Khi biết chắc chắn số phần tử sẽ thêm
  • Tránh cấp phát lại bộ nhớ nhiều lần
  • Tăng tốc độ thêm phần tử

2D Vector — Ma trận động

Khai báo 2D vector

1
2
3
4
5
// Ma trận 3x4, khởi tạo 0
vector<vector<int>> a(3, vector<int>(4, 0));

// Ma trận 3x4, chưa khởi tạo
vector<vector<int>> b(3, vector<int>(4));

Truy cập và sửa

1
2
3
4
5
6
7
8
9
vector<vector<int>> a(3, vector<int>(4, 0));

// Truy cập
cout << a[0][0] << endl;  // 0
cout << a[1][2] << endl;  // 0

// Sửa
a[0][0] = 10;
a[1][2] = 20;

Duyệt 2D vector

vector<vector<int>> a = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// Duyệt theo chỉ số
for (int i = 0; i < a.size(); i++) {
    for (int j = 0; j < a[i].size(); j++) {
        cout << a[i][j] << " ";
    }
    cout << endl;
}

// Duyệt bằng range-based for
for (auto &row : a) {
    for (int x : row) {
        cout << x << " ";
    }
    cout << endl;
}

Vector không đều (Jagged Array)

// Mỗi hàng có số cột khác nhau
vector<vector<int>> a;
a.push_back({1, 2, 3});
a.push_back({4, 5});
a.push_back({6, 7, 8, 9});

for (auto &row : a) {
    for (int x : row) cout << x << " ";
    cout << endl;
}

Erase & Insert

Xóa phần tử

1
2
3
4
5
6
7
8
9
vector<int> a = {1, 2, 3, 4, 5};

// Xóa phần tử tại vị trí 2 (index 2)
a.erase(a.begin() + 2);
// a = {1, 2, 4, 5}

// Xóa từ vị trí 1 đến 3
a.erase(a.begin() + 1, a.begin() + 3);
// a = {1, 5}

Chèn phần tử

1
2
3
4
5
6
7
8
9
vector<int> a = {1, 2, 3, 4, 5};

// Chèn giá trị 10 vào vị trí 2
a.insert(a.begin() + 2, 10);
// a = {1, 2, 10, 3, 4, 5}

// Chèn 3 giá trị 7 vào vị trí 0
a.insert(a.begin(), 3, 7);
// a = {7, 7, 7, 1, 2, 10, 3, 4, 5}

Common Mistakes — Lỗi thường gặp

Lỗi 1: Iterator invalidated

vector<int> a = {1, 2, 3, 4, 5};

// ❌ SAI: Iterator invalidated sau khi erase
for (auto it = a.begin(); it != a.end(); it++) {
    if (*it % 2 == 0) a.erase(it);  // Lỗi!
}

// ✅ ĐÚNG
for (auto it = a.begin(); it != a.end(); ) {
    if (*it % 2 == 0) it = a.erase(it);
    else it++;
}

Lỗi 2: Truy cập ngoài 2D vector

vector<vector<int>> a(3, vector<int>(4, 0));

// ❌ SAI: Truy cập a[3][4]
cout << a[3][4] << endl;  // Lỗi!

// ✅ ĐÚNG: Chỉ truy cập a[0..2][0..3]
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 4; j++) {
        cout << a[i][j] << " ";
    }
}

Bài tập thực hành

Bài 1: Chuyển vị ma trận

Đọc ma trận m×n. In ra ma trận chuyển vị.

Input:

1
2
3
2 3
1 2 3
4 5 6
Output:
1
2
3
1 4
2 5
3 6

Lời giải
#include <bits/stdc++.h>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;
    vector<vector<int>> a(m, vector<int>(n));
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            cin >> a[i][j];
        }
    }

    // In ma trận chuyển vị
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < m; i++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Tóm tắt bài học

Nội dung Chi tiết
Iterator auto it = a.begin(); — con trỏ vào vector
Resize a.resize(n) — thay đổi kích thước
Reserve a.reserve(n) — dự phòng bộ nhớ
2D Vector vector<vector<int>> a(m, vector<int>(n))
Erase a.erase(a.begin() + i) — xóa phần tử
Insert a.insert(a.begin() + i, x) — chèn phần tử

Bài viết liên quan


Bài tiếp theo: C12: Set & Map →


💬 Bình luận