# 【3-4】動態陣列 — vector 在 [【3-1】一維陣列](https://hackmd.io/@LAfWxjSxRASps-4O_bppsA/SkIWNv0Eel)、[【3-3】二維陣列](https://hackmd.io/@LAfWxjSxRASps-4O_bppsA/rklX2HZHll) 我們學習到了陣列,但受限於一開始就要給定長度,有些時候我們是不知道長度是多少的,就會發生裝不下或者浪費記憶體空間的事情。有沒有什麼方法可以解決呢? ## vector `vector` 是 STL(標準模板庫)中的一種容器,可以想成動態陣列。相較我們之前學習的陣列,`vector` 提供了「不需要預先設定大小」的優勢,並且可以很方便的插入或刪除陣列中任何位置的資料,讓我們看看 `vector` 的語法吧! ### 宣告 ```cpp // 一維陣列 vector<int> v1; // 空的 vector,元素類型為 int vector<int> v2(10); // 大小為 10 的 vector,元素初始值為 0 vector<int> v3(10, 5); // 大小為 10 的 vector,所有元素初始值為 5 vector<int> v4 = {1, 2, 3, 4, 5}; // 初始化列表 // 二維陣列 vector<vector<int>> v5; // 空的二維 vector,元素類型為 int ``` ### Python對照 ```python v1 = [] # 空的 list v2 = [0] * 10 # 大小為 10,初始值為 0 v3 = [5] * 10 # 大小為 10,初始值為 5 v4 = [1, 2, 3, 4, 5] # 初始化列表 v5 = [] # 空的二維 list ``` ### 插入資料 ```cpp v.push_back(5); // 在 vector 的尾端插入元素 5 v.insert(v.begin(), 3); // 在 vector 的開頭插入元素 3 v.insert(v.begin() + 2, 7); // 在 vector 的第三個位置插入元素 7 ``` `begin()` 是一種迭代器(iterator),在[【3-6】迭代器](https://hackmd.io/@LAfWxjSxRASps-4O_bppsA/S16spNGrxg) 會詳細介紹,目前可以把 `v.begin()` 看成 `v[0]` 就好了。 ### Python對照 ```python v.append(5) # 在尾端插入元素 5 v.insert(0, 3) # 在開頭插入元素 3 v.insert(2, 7) # 在第 3 個位置插入元素 7 ``` ### 刪除資料 ```cpp v.pop_back(); // 刪除 vector 最尾端的元素 v.erase(v.begin()); // 刪除 vector 開頭的元素 v.erase(iterator); // 刪除 vector 中 iterator 所指的元素 v.erase(v.begin()+1, v.begin() + 4); // 刪除 vector 中第 2 ~ 4個元素 v.erase(iterator1, iterator2); // 刪除 vector 中 iterator1 到 iterator2 的元素 v.clear(); // 刪除所有元素 ``` ### Python對照 ```python v.pop() # 刪除最後一個元素 del v[0] # 刪除第一個元素 del v[1:4] # 刪除第 2 到第 4 個元素 v.clear() # 清空所有元素 ``` ### 其它 ```cpp v.size(); // 回傳 vector 目前的大小 v.resize(5); // 調整 vector 大小為 5 swap(v1, v2); // 交換兩個 vector 的元素 v.empty(); // 回傳一個 bool ,如果 vector 為空回傳 True,反之 False ``` ### Python對照 ```python len(v) # 取得大小 v = v[:5] # 裁切長度(或用 v.extend() 增長) v1, v2 = v2, v1 # 交換兩個 list len(v) == 0 # 判斷是否為空 ``` ### 輸入 * 當題目敘述有「第一行輸入一個整數 $\text{n}$ ,接下來有 $\text{n}$ 行的測試資料」時可以使用下方寫法。 傳統陣列版本: ```cpp= #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; // 資料總數 int a[n]; // 宣告一個大小為 n 的 陣列 for (int i = 0; i < n; i++) { cin >> a[i]; // 讀取使用者輸入的數字 } for (int i = 0; i < n; i++) { cout << a[i] << " "; // 輸出每個數字 } return 0; } ``` `vector` 版本: ```cpp= #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; // 資料總數 vector<int> v(n); // 宣告一個大小為 n 的 動態陣列 for (int i = 0; i < n; i++) { cin >> v[i]; // 讀取使用者輸入的數字 } for (int i = 0; i < n; i++) { cout << v[i] << " "; // 輸出每個數字 } return 0; } ``` ### Python對照 ```python= n = int(input()) a = list(map(int, input().split())) # 一次讀入多筆 ``` * 當題目敘述有「測試資料有數筆,當輸入 0 時終止」時可以使用下方寫法。 ```cpp= #include <bits/stdc++.h> using namespace std; int main() { vector<int> v; // 宣告一個空的 vector int n; while (cin >> n) { if(n == 0){ // 預設終止條件為 0 (此處可以根據題目條件更改) break; } v.push_back(n); // 將輸入的數字加入 vector } for (int i = 0; i < v.size(); i++) { // 用 v.size() 來取得陣列大小 cout << v[i] << " "; } return 0; } ``` ### Python對照 ```python= v = [] while True: n = int(input()) if n == 0: break v.append(n) ``` ## pair 正常來說,陣列中的每一格只能儲存一個資料,但有些時候測試資料會存在前後關聯性,例如說該產品的「成本」和「利益」,這時候分成兩個 `vector` 儲存,在進行某些操作時可能會出問題,像是排序,如果對「成本」進行小到大排序,利益就無法對齊原本的成本,但若使用 `pair` 來處理,就可以把這個產品的「成本」和「利益」綁在一起,移動的時候也一起搬,這樣就不會亂掉了! ### 範例 題目:請根據成本從低到高的順序,輸出每個產品的利益,數字之間用空格分隔。 | 產品編號 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 成本 | 50 | 60 | 30 | 10 | 80 | 40 | 90 | | 利益 | 60 | 40 | 50 | 80 | 90 | 30 | 10 | 解題思路:先將產品按照成本排序,再依序輸出該產品的利益。 ### 輸入 把成本跟利益輸入後,得到兩個一維陣列: | index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 成本 | 50 | 60 | 30 | 10 | 80 | 40 | 90 | | index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 利益 | 60 | 40 | 50 | 80 | 90 | 30 | 10 | 此時的 index +1 就會是產品編號。 ### 照成本排序 | index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 成本 | 10 | 30 | 40 | 50 | 60 | 80 | 90 | 你會發現,確實排序好了,但我不知道產品編號。只知道成本低到高分別是多少。 ### 先 pair 再排序 所以這時候我們就要使用 `pair` 來幫助我們把兩個資料儲存成「一組」,放在一起。 (請注意,現在只有一個 `vector` !但是這個 `vector` 的每一個格子可以存放兩個整數。) | index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 成本 | 50 | 60 | 30 | 10 | 80 | 40 | 90 | | 利益 | 60 | 40 | 50 | 80 | 90 | 30 | 10 | 排序後得到: | index | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | -------- | --- | --- | --- | --- | --- | --- | --- | | 成本 | 10 | 30 | 40 | 50 | 60 | 80 | 90 | | 利益 | 80 | 50 | 30 | 60 | 40 | 90 | 10 | 你會發現,同一個產品的成本和利益被綁在一起了,所以排序的時候會一起移動。 ### 宣告 ```cpp vector<pair<int, int>> v; ``` ![image](https://hackmd.io/_uploads/SJybx901Jl.png) 可以看到 `pair` 後的陣列的每格都可以儲存兩個資料。第一格叫 `.first`,第二格叫 `.second`,記得一定要加「`.`」喔! ### 範例程式 ```cpp= #include <bits/stdc++.h> using namespace std; int main(){ int n; // 有 n 筆資料 cin >> n; vector<pair<int,int>> v(n); // 輸入 for(int i = 0; i < n; i++){ int x, y; cin >> x >> y; v[i] = {x, y}; } // 輸出 for(int i = 0; i < n; i++){ cout << v[i].first << " " << v[i].second << endl; } return 0; } ``` ### Python對照 ```python= n = int(input()) v = [] for _ in range(n): x, y = map(int, input().split()) v.append((x, y)) for x, y in v: print(x, y) ``` --- 聯絡方式:codecodefunny@gmail.com 最後編修時間:2025/11/14 子柚筆