set本質上是一棵紅黑樹,用法也就那么幾個,插入刪除lowerbound,再就是迭代器之類的
基本用法
begin()--返回指向第一個元素的迭代器

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); printf("%d",*s.begin()); //輸出4 return 0; }
end()--返回指向最后一個元素的迭代器

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); printf("%d",*s.end()); //注意這里的跌倒器指向的是一個空位置! //所以最好不要輸出end() //輸出末尾元素可以用下面的方法 //std::set<int>::iterator it=s.end(); //printf("%d",*--it); return 0; }
rbegin()--返回指向集合中最后一個元素的反向迭代器
rend()--返回指向集合中第一個元素的反向迭代器
find()--返回一個指向被查找到元素的迭代器
insert()--在集合中插入元素
size()--集合中元素的數目
clear()--清除所有元素

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); printf("%d\n",s.size()); s.clear(); printf("%d\n",s.size()); return 0; }
count()--返回某個值元素的個數//主要應用於multiset

#include<cstdio> #include<set> int main() { std::multiset<int>s; s.insert(5); s.insert(5); s.insert(6); printf("%d",s.count(5)); return 0; }
empty()--如果集合為空,返回true
erase()--刪除集合中的元素
erase可以刪除給定的元素,也可以刪除迭代器
在multiset中,刪除給定的元素是全部刪除,而刪除迭代器只會刪除一次,下面還會講到

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); s.erase(5); s.erase(s.find(4)); if(s.find(5)==s.end()) printf("5 is not found\n"); if(s.find(4)==s.end()) printf("4 is not found\n"); if(s.find(6)!=s.end()) printf("6 is found"); return 0; }
lower_bound()--返回指向大於(或等於)某值的第一個元素的迭代器

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); printf("%d",*s.lower_bound(4)); //輸出為4 return 0; }
upper_bound()--返回大於某個值元素的迭代器

#include<cstdio> #include<set> int main() { std::set<int>s; s.insert(5); s.insert(4); s.insert(6); printf("%d",*s.upper_bound(4)); //輸出為4 return 0; }
swap()--交換兩個集合變量

#include<cstdio> #include<set> int main() { std::set<int>s; std::set<int>a; s.insert(4); s.insert(5); a.insert(6); s.swap(a); printf("%d",s.size()); //輸出為1 return 0; }
幾個常用操作
正序遍歷所有元素
這個需要借助迭代器來實現
set中是重載了迭代器的++和--運算符的,所以直接使用就可以了
#include<cstdio> #include<set> #define sit set<int>::iterator using namespace std; int main() { set<int>s; for(int i=1;i<=10;i++) s.insert(i); for(sit i=s.begin();i!=s.end();i++) printf("%d ",*i); //輸出1 2 3 4 5 6 7 8 9 10 return 0; }
倒序遍歷所有元素
可以使用rbegin和rend實現,他們與begin和end的關系如下圖所示
#include<cstdio> #include<set> #define rsit set<int>::reverse_iterator using namespace std; int main() { set<int>s; for(int i=1;i<=10;i++) s.insert(i); rsit it=s.rbegin(); for(rsit i=s.rbegin();i!=s.rend();i++) printf("%d ",*i); //輸出10 9 8 7 6 5 4 3 2 1 return 0; }
multiset中刪除元素
在multiset中,如果僅僅用erase($x$)來刪除$x$元素,那么$x$的出現次數會變為$0$
解決方法是先找到$x$對應的迭代器,然后將迭代器刪除,這樣就可以使$x$只刪除一次
#include<cstdio> #include<set> #define sit set<int>::iterator using namespace std; int main() { multiset<int>s; s.insert(2); s.insert(2); s.insert(2); s.erase(2); printf("%d\n",s.count(2)); s.insert(2); s.insert(2); s.insert(2); s.erase(s.find(2)); printf("%d\n",s.count(2)); //輸出0 2 return 0; }
自定義排序規則
如果元素不在結構體中,需要自定義結構體並重載“$()$”運算符
#include<cstdio> #include<set> #define sit set<int>::iterator using namespace std; struct comp { bool operator ()(const int &a,const int &b) { return a>b; } }; int main() { set<int,comp>s; for(int i=1;i<=10;i++) s.insert(i); for(sit i=s.begin();i!=s.end();i++) printf("%d ",*i); //輸出10 9 8 7 6 5 4 3 2 1 return 0; }
若元素在結構體中,則需要重載$<$運算符
#include<cstdio> #include<set> #define sit set<node>::iterator using namespace std; struct node { int l,r; node(int l=0,int r=0):l(l),r(r){}; bool operator < (const node &a) const { return r==a.r?l<a.l:r<a.r; } }; int main() { set<node>s; for(int i=1;i<=10;i++) s.insert(node(i,10-i+1)); for(sit i=s.begin();i!=s.end();i++) printf("%d %d\n",i->l,i->r); //輸出 /* 10 1 9 2 8 3 7 4 6 5 5 6 4 7 3 8 2 9 1 10 */ return 0; }
在結構體中二分
只要重載了$<$,就可以在結構體中二分了
#include<cstdio> #include<set> #define sit set<node>::iterator using namespace std; struct node { int l,r; node(int l=0,int r=0):l(l),r(r){}; bool operator < (const node &a) const { return r==a.r?l<a.l:r<a.r; } }; int main() { set<node>s; for(int i=1;i<=10;i++) s.insert(node(i,i)); sit it=s.lower_bound(node(1,2)); printf("%d %d",it->l,it->r); //輸出 2 2 return 0; }
題目
都是可以用set水的大水題