# 【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;
```

可以看到 `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 子柚筆