轉載請註明出處,部份內容引自李煜東《算法競賽進階指南》node
前置知識: C++、C語言入門算法
Set是什麼函數
Set是C++STL中提供的容器,set是數學上的集合——具備惟一性,即每一個元素只出現一次,而multiset則是可重集,二者的內部實現是一棵紅黑樹,它們支持的函數基本相同spa
Set的相關操做code
頭文件blog
#include<set>
聲明:排序
像這樣:數學
set<類型>名稱;
好比:it
set<int>s; set<vector<int> >s; //vector中提供重載<
set<set<int> >s; //平衡樹嵌套,哈哈
multiset<double>s;
就像其餘須要排序的數據類型同樣,爲一個結構體的set,須要重載小於號入門
struct node{ ......; }; set<node>s; bool operator <(const node &ai,const node &bi) { return ai.x>bi.x; }
set.size()
統計set中元素個數,函數返回一個整形變量,表示set中元素個數,時間複雜度O(1)
用法:名稱.size(); eg. int num=s.size();
set.empty()
檢查set是否爲空,返回一個bool型變量,1表示set爲空,不然爲非空,時間複雜度O(1)
用法:名稱.empty(); eg. if(s.empty()) cout<<"Myset is Empty."<<endl;
set.clear()
清空set,無返回值
用法:名稱.clear();
eg.
s.clear();
set.count(x)
返回set或multiset中值爲x的元素個數,時間複雜度爲O(log n)
用法:名稱.count(x) eg. if(!s.count(x)) ans++;
迭代器
雙向訪問迭代器,不支持隨機訪問,支持星號解除引用,僅支持「++」,「--」這兩個算術操做
引用和操做:
set<類型>::iterator it; eg. set<int>::iterator it=s.begin(); it++; it--;
若把it++,則it將會指向「下一個」元素。這裏的下一個是指在key從小到大排序的結果中,排在it下一名的元素。同理,若把it--,則it會指向排在上一個的元素
「++」,「--」操做的複雜度均爲O(log n)
遍歷set及訪問其中的元素
//set
for(set<int>::iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl; //取出這個迭代器指向的元素 //set嵌套
for(set<set<int> >::iterator it=s.begin();it!=s.end();it++) { //首先取出set中嵌套的set
for(set<int>::iterator rit=(*it).begin();rit!=(*it).end();rit++) cout<<*rit<<' '; //遍歷這個set
cout<<endl; }
set.begin()
返回集合的首迭代器,即指向集合中最小元素的迭代器,時間複雜度爲O(1)
用法:名稱.begin(); eg. map<int>::iterator it=s.begin();
set.end()
返回集合的尾迭代器,衆所周知,STL中區間都是左閉右開的,那麼end()函數返回的迭代器即爲指向集合中最大元素的下一個位置的迭代器,所以--s.end()纔是指向集合中最大元素的迭代器,時間複雜度爲O(1)
用法:名稱.end(); eg. maxn=*(--s.end()); //取出最大元素
set.insert(x)
在set中插入元素,返回插入地址的迭代器和是否插入成功的bool併成的pair,時間複雜度爲O(log n)
PS:set在進行插入的時候是不容許有重複的鍵值的,若是新插入的鍵值與原有的鍵值重複則插入無效(multiset能夠重複)
用法:名稱.insert(set類型); eg. s.insert(3);
set.erase(參數)
刪除,參數能夠是元素或者迭代器,返回下一個元素的迭代器,時間複雜度爲O(log n),注意在multiset中s.erase(x)會刪除全部值爲x的元素
用法:名稱.erase(參數); eg. set<int>::iterator it=s.begin(); s.erase(it); s.erase(3);
set.find(x)
在set中查找值爲x的元素,並返回指向該元素的迭代器,若不存在,返回set.end(),時間複雜度爲O(log n)
用法:名稱.find(x); eg. if(s.find(x)!=s.end()) cout<<"Have Found!"<<endl;
set.lower_bound(x)/upper_bound(x)
兩個神奇的東西,決定把他們放在一塊談一談
用法與find相似,但查找的條件略有不一樣,時間複雜度O(log n)
s.lower_bound(x)表示查找>=x的元素中最小的一個,並返回指向該元素的迭代器
s.upper_bound(x)表示查找>x的元素中最小的一個,並返回指向該元素的迭代器
舉個例子:
在set{3,5,7,8,13,16}中
對於在set中存在的元素,好比8
s.lower_bound(8)返回8所在位置的迭代器
s.upper_bound(8)返回13所在位置的迭代器
對於在set中不存在的元素,好比12
兩個函數返回的則都是13所在位置的迭代器
特殊地,
對於比set中最大的元素大的元素,好比20
兩個函數返回的都是s.end()