# STL - 2
---
# 集合 set
----
* 大小不固定
* 同個東西只有一個
* 沒有隨機存取,但有順序
----
```cpp=
// 創建
set<int> set1; // 創造空集合
set<int> set2{2, 1, 3, 4}; // 給集合初始元素
// 集增加、修改、刪除元素
set1.insert(0); // 加入元素
int c = set2.erase(3); // 刪除元素,回傳刪了幾個
int cnt = set2.count(4); // 回傳有幾個指定元素
// 集合整體
int len = set2.size(); // 集合大小
bool emp = set1.empty(); // 是否沒有元素
set1.clear(); // 清空集合
```
----
```cpp=11
// 迭代器
for (auto it = set2.begin(), it != set2.end(), it++){
cout << *it << ' '; // 迭代遍歷
} // 反向遍歷用 .rbegin(), .rend()
// 1 2 4
for (auto &i : set2){} // 另一種遍歷方法
auto it = set2.find(4); // 找元素的迭代器,找不到會回傳.end()
set2.erase(it); // 刪除迭代器指向的位置
```
----
## 練習題
[ZJ d478.](https://zerojudge.tw/ShowProblem?problemid=d478)
----
## unordered_set
跟set幾乎一樣,但是不會排序。
後加入的就會在迭代器較後面。
----
## multiset
也是set,但允許重複元素
如果 .erase() 元素名,會刪除全部相同的元素
.erase() 和 .count() 都會回傳元素數量
----
## unordered_multiset
具有unordered_set和multiset兩種特性的set
不會排序,而且元素可以重複
---
# 配對 pair
----
- pair可以將兩個資料綁在一起
- pair的兩個值可以是不同類型
- 如果是兩項都可以比,則同類的pair也可以比
- 會先比前項,再比後項
----
```cpp=
// 創造
pair<int, char> p1(100, 'a'), p2(10, 'c'); // 初始化pair
auto p3 = make_pair<int, char>(5, 'z'); // 用make_pair創造
// 改變、讀取
p1.first = 10; // .first 和 .second 可以存取個別的
cout << p1.first << ' ' << p1.second << '\n';
// 比較
cout << (p1>p3) << '\n'; // true,比first,10>5,所以p1>p3
cout << (p1>p2) << '\n'; // false
// 先比first,10==10,比second,'a'<'c',所以p1<p2
```
----
- 常搭配陣列,用來排序的同時保持關係
[ZJ h075.](https://zerojudge.tw/ShowProblem?problemid=h075)
[ZJ d536.](https://zerojudge.tw/ShowProblem?problemid=d536)
---
# 字典 map
----
- map類似vector,但會一次儲存兩個值
- 第一個值是索引,不會重複
- 第二個值是元素,要用索引來存取
- 會依索引排序,預設由小到大
----
```cpp=
// 創造
map<string, int> map1;
map<string, int> map2 = {{"wow",1}, {"hi",2}};
// 存取、修改、增加、刪除
cout<<map2["hi"]<<'\n'; // 回傳索引"hi"對應元素
map2["wow"] = 0; // 把"wow"對應的元素改成0
map1["who"] = 100; // 新增索引"who",對應元素100
map2.insert(pair<string,int>("here", 5)); // 用pair來新增
int c = map2.erase("wow"); // 刪除索引"wow",回傳刪了幾個
int cnt = map2.count("hi"); // 尋找索引是"hi"的有幾個
auto it = map2.find("wow"); // 找指向索引是"wow"的迭代器
//因為找不到,所以回傳map2.end()
```
----
```cpp=13
// 整體
int len = map2.size(); // 回傳map2有幾項
bool emp = map1.empty(); // 回傳map1是否是空的
map1.clear(); // 清空map1
// 遍歷
for(auto i : map2){ // i會是pair
cout<<i.first<<' '<<i.second<<'\n';
}
for (auto it = map2.begin(); it != map2.end(); it++) // 迭代器
```
----
## unordered_map
不會依索引排序的map
依時間先後排序
會比map稍微快一點。
----
## multimap
同個索引可以對到多個元素,無法直接以索引存取
同索引依先後順序排序
許多和map的差異就像multiset和set的差異
像是pair的vector
----
## unordered_multimap
同時unordered又multi的map
不排序,不能直接存取,可以重複索引
---
# 元組 tuple
----
- tuple可以建立容納多種類型的元素
- 如果內容物允許比較,tuple就可以比較
----
```cpp=
// 創建
tuple<int, int, double> tuple1(10, 2, 0.5);
auto tuple2 = make_tuple<int, int, double>(0, 8, 1.0);
// 存取、變更
cout << get<1>(tuple1) << '\n'; // 得到tuple1的第二項
get<0>(tuple2) = 10; // 將tuple2的第一項改成10
// 拆開
int i1, i2; double d1;
tie(i1, i2, d1) = tuple1; // i1=10, i2=2, d1=0.5
// 比較
cout << (tuple1>tuple2); // 先比10==10,接著2<8,所以是false
```
----
## 練習題
[ZJ a362.](https://zerojudge.tw/ShowProblem?problemid=a362)
{"title":"STL - 2","contributors":"[{\"id\":\"00ad9127-6491-4b3d-829b-7847a217f8e5\",\"add\":3952,\"del\":829}]","description":"標準程式庫"}