SET集合
事前準備
#include<set>
using namespace std;
int main(){
}REd-black tree紅黑樹
set其實就是一棵紅黑樹
甚麼是紅黑樹?
REd-black tree紅黑樹
A red-black tree is a binary search tree with the following properties:
-
Every node is colored with either red or black.
-
All leaf (nil) nodes are colored with black; if a node’s child is missing then we will assume that it has a nil child in that place and this nil child is always colored black.
-
Both children of a red node must be black nodes.
-
Every path from a node n to a descendent leaf has the same number of black nodes (not counting node n). We call this number the black height of n, which is denoted by bh(n).
好複雜喔看不懂怎麼辦?
沒關係我也看不懂
其實set就是一棵二元搜索樹(BST)
還是不懂嗎?沒關係會用就好
set基本操作
set基本操作
set<int> s;宣告一個 set
set裡面的每個元素都是唯一的(不會有重複)
set裡面的元素會自動排序(預設由小到大)
插入操作
s.insert(10)時間複雜度O(log N) N是集合大小
插入一個數到集合中
如果集合裡已經有10那什麼事都不會發生
刪除操作
s.erase(10)時間複雜度O(log N) N是集合大小
刪除一個集合中數(也可以用迭代器刪除)
如果集合裡沒有10, 那...你可能會Runtime Error
那怎麼避免呢?可以先加個判斷
查詢操作
if(s.find(10) != s.end())s.end()會回傳s指向最後的迭代器
指向最後的迭代器並不是指向最後一個集合中元素
s.find(x)會回傳指向x的迭代器
如果x不再集合中會回傳會與s.end()相同
set其他操作
s.begin()
//回傳第一個元素的迭代器
s.rbegin()
//回傳第一個反指標
//指向元素跟prev(s.end())相同
s.size()
//回傳集合大小
set<int,greater<int>> s;
//宣告一個由大到小的集合iterator迭代器小教室
iterator迭代器小教室
到底什麼是迭代器?
簡單來說就是幫助你遍歷STL容器的指標
不懂什麼是指標嗎?
指標會告訴你你要的變數存在哪裡
當然你就可以透過指標存取到你想要的變數
iterator迭代器小教室
迭代器其實是一種資料型態喔
要怎麼宣告呢?
vector<int> :: iterator vit;
//宣告一個 vector<int>的迭代器
set<int> :: iterator sit;
//宣告一個 set<int>的迭代器iterator迭代器小教室
哭阿怎麼這麼麻煩?有沒有簡單一點的方法
有喔!利用C++11以上提供的auto
auto it;
// 錯誤用法 auto只是幫你自動判斷
// 並不是真的有這個資料型態
auto sit = s.begin();
// 正確用法
// sit 會被判斷為 set<int> :: iterator
// 反正記得使用auto一定要完整初始化iterator迭代器小教室
那要怎麼取到迭代器指向的值呢?
加個星號*就好了喔
要怎麼求集合S裡的第二個數呢?
可以使用 it++ || it = next(it)
auto it = s.begin();
cout << *it << '\n';
//輸出集合s第一個(最小)元素的值
it++; // 等價於 it = next(it);
cout << *it << '\n';
//輸出集合s第二個元素的值
auto itend = prev(s.end());
//雖然s.end()指向的不是集合中元素
//但它的前一個就是集合中的最後一個
iterator迭代器小教室
順便教一下range base for迴圈的用法
就是跟python很像的那種for迴圈
可以幫你輕鬆遍歷所有STL容器
set<int> s;
for(int x = 0; x < 10; x++)
s.insert(x);
for(int i : s)
cout << i << ' ';
//輸出會是0到9
//迴圈裡的i就會是集合裡的元素喔iterator迭代器小教室
其實set有內建的upper_bound和lower_bound
時間複雜度都是O(log N),因為是在BST上做二分搜
但他們的回傳值都是iterator
所以強烈建議大家學好iterator,才能靈活運用
set<int> s
for(int x = 0; x < 10; x++)
s.insert(i);
auto it = s.lower_bound(5);
cout << *it << '\n'; //輸出5
auto it = s.upper_bound(5);
cout << *it << '\n'; //輸出6set實戰演練
set實戰演練
我們現在知道set可以快速的插入 ,刪除 ,取最大最小值
那請問...pq還有什麼用
pq能做到的set都可以(但set會稍微慢一點)
但是set不是不允許重複元素嗎?
用multiset就可以完美解決了(用法跟set幾乎完全相同)
multiset<int> s;set實戰演練
還記的pq可以做什麼嗎?通通用set重作一遍!!
我們先來一題簡單的
題目就是要你完成插入和取最大最小並刪除這幾個操作
根本就是set模板題阿
其實用set有點投機取巧但能做就好
set實戰演練
這邊提醒一下大家記得使用multiset因為回有重複數字
然後multiset使用有個特殊的地方
如果你想刪除multiset裡的值為x的元素的話
使用s.erase(x)會把所有值為x都刪除
如果要只刪除一個的話要這樣打
s.erase(s.find(x));set進階挑戰
thanks for listening
MINGDAO CPP SET講義
By Gilbert Yeh
MINGDAO CPP SET講義
這個人懶死了,甚麼都沒有寫。
- 370