std::vector
是 C++ 中一種常用的動態陣列容器,它可以自動調整大小,並提供方便的操作方法。本文將透過三個範例教學來詳細介紹 vector
的使用、迭代器的應用,以及為什麼迭代器在某些情況下比指標更適合。
函式速查表
1. 向量初始化
函式 |
功能 |
範例 |
vector<T> v; |
建立空的向量 |
vector<int> v; |
vector<T> v(n, val); |
建立大小為 n 的向量,初始值為 val |
vector<int> v(5, 0); |
vector<T> v{val1, val2}; |
使用初始列表初始化向量 |
vector<int> v{1, 2, 3}; |
vector<T> v(v2); |
複製另一個向量 |
vector<int> v2 = v; |
vector<T> v(v2.begin(), v2.end()); |
初始化為另一範圍 |
vector<int> v(v2.begin(), v2.begin() + 3); |
vector<vector<T>> mat; |
建立空的二維向量 |
vector<vector<int>> mat; |
vector<vector<T>> mat(rows, vector<T>(cols)); |
建立大小為 rows x cols 的二維向量 |
vector<vector<int>> mat(3, vector<int>(4)); |
vector<vector<T>> mat(rows, vector<T>(cols, val)); |
建立並初始化所有元素為 val |
vector<vector<int>> mat(3, vector<int>(4, -1)); |
2. 基本操作
函式 |
功能 |
範例 |
v.push_back(val); |
在向量末尾添加元素 |
v.push_back(10); |
v.pop_back(); |
刪除向量末尾的元素 |
v.pop_back(); |
v.size(); |
返回向量的大小 |
cout << v.size(); |
v.capacity(); |
返回向量的容量(記憶體分配空間) |
cout << v.capacity(); |
v.empty(); |
判斷向量是否為空 |
if (v.empty()) { cout << "Empty"; } |
v.clear(); |
清空所有元素 |
v.clear(); |
3. 訪問元素
函式 |
功能 |
範例 |
v[i]; |
使用索引訪問元素 |
cout << v[0]; |
v.at(i); |
安全訪問第 i 個元素(會檢查邊界) |
cout << v.at(0); |
v.front(); |
返回第一個元素 |
cout << v.front(); |
v.back(); |
返回最後一個元素 |
cout << v.back(); |
v.data(); |
返回指向底層數據的指標 |
int* p = v.data(); cout << p[0]; |
4. 修改向量
函式 |
功能 |
範例 |
v.insert(pos, val); |
在指定位置 pos 插入元素 val |
v.insert(v.begin(), 10); |
v.insert(pos, n, val); |
在 pos 插入 n 個值 val |
v.insert(v.begin(), 3, 10); |
v.erase(pos); |
刪除指定位置的元素 |
v.erase(v.begin() + 1); |
v.erase(start, end); |
刪除範圍內的元素 |
v.erase(v.begin() + 1, v.begin() + 3); |
v.resize(n); |
調整向量大小為 n (多出部分為默認值) |
v.resize(5); |
v.resize(n, val); |
調整大小為 n ,多出部分填充為 val |
v.resize(5, 0); |
v.swap(v2); |
與另一個向量 v2 交換內容 |
v.swap(v2); |
5. 迭代器相關
函式 |
功能 |
範例 |
v.begin(); |
返回指向第一個元素的迭代器 |
auto it = v.begin(); |
v.end(); |
返回指向最後一個元素下一位置的迭代器 |
for (auto it = v.begin(); it != v.end(); ++it) { cout << *it; } |
v.rbegin(); |
返回指向最後一個元素的反向迭代器 |
for (auto it = v.rbegin(); it != v.rend(); ++it) { cout << *it; } |
v.rend(); |
返回指向第一個元素前一位置的反向迭代器 |
|
v.cbegin(); |
返回指向第一個元素的常量迭代器 |
auto it = v.cbegin(); |
v.cend(); |
返回指向最後一個元素下一位置的常量迭代器 |
|
v.crbegin(); |
返回指向最後一個元素的反向常量迭代器 |
|
v.crend(); |
返回指向第一個元素前一位置的反向常量迭代器 |
|
6. 容量操作
函式 |
功能 |
範例 |
v.reserve(n); |
預留至少 n 的空間 |
v.reserve(100); |
v.shrink_to_fit(); |
將容量縮小為當前大小 |
v.shrink_to_fit(); |
1. std::vector
的基本使用
vector
的特性
- 動態大小:可以根據需求自動調整容量。
- 隨機存取:支持索引操作,與普通陣列類似。
- 內建方法:提供高效的插入、刪除等功能。
- 與 STL 演算法整合:可以與
sort
等標準函數配合使用。
範例 1:逐步刪除並反轉 vector
的元素
題目描述:
- 輸入一個整數 ( n ),表示有 ( n ) 個元素,然後輸入這些元素。
- 打印出當前的所有元素。
- 刪除第一個元素。
- 反轉剩餘的元素。
- 重複步驟 2-4,直到元素全部刪除。
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <iostream> #include <vector> #include <algorithm>
using namespace std;
int main() { int n, num; cin >> n; vector<int> vec; for (int i = 0; i < n; ++i) { cin >> num; vec.push_back(num); }
while (!vec.empty()) { for (const auto &x : vec) { cout << x << " "; } cout << endl;
vec.erase(vec.begin());
reverse(vec.begin(), vec.end()); }
return 0; }
|
執行範例
輸入:
輸出:
1 2 3 4 5
| 1 3 5 7 9 9 7 5 3 3 5 7 7 5 5
|
程式解說
- 使用
vector<int>
存儲輸入數字。
- 使用
erase(vec.begin())
刪除第一個元素。
- 使用
reverse(vec.begin(), vec.end())
反轉向量。
- 使用範圍式
for
迴圈打印元素。
2. 交換 vector
中的列
範例 2:交換矩陣中指定的兩列
題目描述:
- 輸入一個 ( n \times n ) 的矩陣。
- 輸入兩個整數 ( a ) 和 ( b ),交換矩陣中第 ( a ) 列和第 ( b ) 列。
- 打印交換後的矩陣。
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> #include <vector> using namespace std;
int main() { int n, a, b;
cin >> n;
vector<vector<int>> matrix(n, vector<int>(n));
for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { cin >> matrix[i][j]; } }
cin >> a >> b;
for (int i = 0; i < n; ++i) { swap(matrix[i][a], matrix[i][b]); }
for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { cout << matrix[i][j] << " "; } cout << endl; }
return 0; }
|
執行範例
輸入:
輸出:
程式解說
- 使用
vector<vector<int>>
存儲矩陣。
- 使用
swap(matrix[i][a], matrix[i][b])
交換指定的兩列。
- 打印矩陣時使用雙層迴圈遍歷。
3. 使用迭代器查找非重複數字
題目描述:
- 輸入兩組數字,找出它們中不重複的數字。
- 使用
vector
實現。
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <iostream> #include <vector> #include <algorithm>
using namespace std;
int main() { int n, m, num;
cin >> n; vector<int> vec1; for (int i = 0; i < n; ++i) { cin >> num; vec1.push_back(num); }
cin >> m; vector<int> vec2; for (int i = 0; i < m; ++i) { cin >> num; vec2.push_back(num); }
vector<int> result;
for (auto it = vec1.begin(); it != vec1.end(); ++it) { if (find(vec2.begin(), vec2.end(), *it) == vec2.end()) { result.push_back(*it); } }
for (auto it = vec2.begin(); it != vec2.end(); ++it) { if (find(vec1.begin(), vec1.end(), *it) == vec1.end()) { result.push_back(*it); } }
sort(result.begin(), result.end()); for (const auto &x : result) { cout << x << " "; }
return 0; }
|
執行範例
輸入:
輸出:
4. 為什麼迭代器比指標更好?
1. 統一性與可讀性
- 迭代器:
- 針對所有 STL 容器(如
vector
, list
, map
等)都可以使用統一的操作方式。
- 使用範例:
1 2 3
| for (auto it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; }
|
- 指標:
- 指標無法適應非連續容器(如
list
)。
- 容易引發記憶體操作錯誤。
2. 安全性
- 迭代器具有更多邊界檢查,避免越界。
- 指標則可能指向未分配的記憶體。
3. 與 STL 算法整合
- 迭代器可直接用於標準演算法,如
std::sort
, std::find
。
- 指標僅能操作基礎陣列。
總結
std::vector
是 C++ 中功能強大的容器,適合動態大小數據的處理。
- 迭代器提供了統一的操作方式,比指標更安全、靈活且易於整合。
- 熟練使用
vector
和迭代器能大大提升程式的效率和可讀性。