STL学习笔记(关联式容器)
Set和Multisets
set和multiset会根据特定的排序准则,自动将元素排序。两者不同在于multisets允许元素重复而set不允许。
1.set和multiset的操作函数
生成、复制和销毁
set c //产生一个空的set/multiset,其中不含任何元素 set c(op) //以op为排序准则,产生一个空的set/mulitset set c1(c2) //产生某个set/multiset的副本,所有元素均被复制 set c(beg,end) //以区间[beg;end)内的元素产生一个set/multiset set c(beg,end,op) //以op为排序准则,利用[beg;end]内的元素生成一个set/multiset c.~set() //销毁所有元素,释放内存
其中set可为下列形式:
set<Elem> //一个set,以less<>(operator<)为排序准则 set<Elem,op> //一个set,以op为排序准则 multiset<Elem> //一个multiset,以less<>(operator<)为排序准则 multiset<Elem,op> //一个multiset,以op为排序准则
特殊的搜寻函数
count(elem) //返回“元素值为elem”的元素个数 find(elem) //返回"元素值为elem"的第一个元素的位置,如果找不到就返回end() lower_bound(elem) //返回elem的第一个可安插位置,也就是“元素值>=elem”的第一个元素位置 upper_bound(elem) //返回elem的最后一个可安插位置,也就是“元素值>elem”的第一个元素位置 equal_range(elem) //返回elem可安插的第一个位置和最后一个位置,也就是“元素值==elem”的元素区间
下面是后面三个函数的一个例子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <set> 3 using namespace std; 4 5 int main() 6 { 7 set<int> c; 8 c.insert(1); 9 c.insert(2); 10 c.insert(4); 11 c.insert(5); 12 c.insert(6); 13 cout<<"lower_bound(3): "<<*c.lower_bound(3)<<endl; 14 cout<<"upper_bound(3): "<<*c.upper_bound(3)<<endl; 15 cout<<"equal_range(3): "<<*c.equal_range(3).first<<" "<<*c.equal_range(3).second<<endl; 16 cout<<endl; 17 cout<<"lower_bound(5): "<<*c.lower_bound(5)<<endl; 18 cout<<"upper_bound(5): "<<*c.upper_bound(5)<<endl; 19 cout<<"equal_range(5): "<<*c.equal_range(5).first<<" "<<*c.equal_range(5).second<<endl; 20 }
赋值
set和multiset只提供所有容器都提供的基本赋值操作
这些操作函数中,赋值操作的两端容器必须具有相容型别,而“比较准则”本身可以不同。如果准则不同,准则本身也会被赋值或交换
c1=c2 //将c2中所有元素赋值给c1 c1.swap(c2) //将c1和c2的元素交换 swap(c1,c2) //同上,此为全局函数
元素的安插和移除
c.insert(elem) //安插一份elem副本,返回新元素位置 c.insert(pos,elem) //安插一份elem副本,返回新元素位置(pos只是个提示) c.insert(beg,end) //将区间[beg;end)内所有元素的副本安插到c(无返回值) c.erase(elem) //移除“与elem相等”的所有元素,返回被移除的元素个数 c.erase(pos) //移除迭代器pos锁指位置上的元素,无返回值 c.erase(beg,end) //移除区间[beg;end)内所有元素,无返回值 c.clear() //移除全部元素,将整个容器清空
因为set的元素不可以重复,因此安插动作可能会失败。为此set提供了如下接口来判断安插动作是否成功:
pair<iterator,bool> insert(const value_type& elem);
其中pair结构中second成员表示安插是否成功,first成员返回新元素的位置。
因为对迭代器操作而言,set和multiset所有元素都被视为常数,因此无法对其元素调用任何变动性算法。例如:remove()(因为remove()算法实际上是以一个参数值覆盖被移除的元素)。
如果要移除元素,只能使用它们所提供的成员函数。
2.set和multiset运用实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <set> 3 #include <iterator> 4 using namespace std; 5 6 int main() 7 { 8 typedef set<int,greater<int> > IntSet; 9 IntSet coll1; 10 coll1.insert(4); 11 coll1.insert(3); 12 coll1.insert(5); 13 coll1.insert(1); 14 coll1.insert(6); 15 coll1.insert(2); 16 coll1.insert(5); 17 IntSet::iterator pos; 18 for(pos=coll1.begin();pos!=coll1.end();++pos) 19 cout<<*pos<<' '; 20 cout<<endl; 21 pair<IntSet::iterator,bool> status=coll1.insert(4); 22 if(status.second) 23 cout<<"4 inserted as element "<<distance(coll1.begin(),status.first)+1<<endl; 24 else 25 cout<<"4 already exists"<<endl; 26 set<int> coll2(coll1.begin(),coll1.end()); 27 copy(coll2.begin(),coll2.end(),ostream_iterator<int>(cout," ")); 28 cout<<endl; 29 coll2.erase(coll2.begin(),coll2.find(3)); 30 int num; 31 num=coll2.erase(5); 32 cout<<num<<" element(s) removed"<<endl; 33 copy(coll2.begin(),coll2.end(),ostream_iterator<int>(cout," ")); 34 cout<<endl; 35 }
Map和Multimap
Map和Multimap将key/value当做元素,进行管理,他们可根据key的排序准则自动将元素排序。multimap允许重复元素(key值),maps不允许。
1.map和multimap的操作函数
生成、复制和销毁(跟set一样)
map c //产生一个空的map/multimap,其中不含任何元素 map c(op) //以op为排序准则,产生一个空的map/mulitmap map c1(c2) //产生某个map/multimap的副本,所有元素均被复制 map c(beg,end) //以区间[beg;end)内的元素产生一个map/multimap map c(beg,end,op) //以op为排序准则,利用[beg;end)内的元素生成一个map/multimap c.~map() //销毁所有元素,释放内存
其中,map可为下列形式:
map<key,Elem> //一个map,以less<>(operator<)为排序准则 map<key,Elem,op> //一个map,以op为排序准则 multimap<key,Elem> //一个multimap,以less<>(operator<)为排序准则 multimap<key,Elem,op> //一个multimap,以op为排序准则
map和multimap也有类似于set和multiset的特殊搜寻操作函数
count(key) //返回“键值为key”的元素个数 find(key) //返回"键值为key"的第一个元素的位置,如果找不到就返回end() lower_bound(key) //返回"键值为key"的元素的第一个可安插位置,也就是“键值>=key”的第一个元素位置 upper_bound(key) //返回“键值为key”的元素的最后一个可安插位置,也就是“键值>key”的第一个元素位置 equal_range(key) //返回“键值为key”的元素可安插的第一个位置和最后一个位置,也就是“键值==key”的元素区间
与set和multiset一样,在map和multimap中(实际型别是pair<const key,T>),所有元素的key都被视为常数,因此不能对其调用任何变动性算法,也不能直接修改key(但是可以修改value)。
map和multimap的元素安插和移除函数跟set和multiset一样。不同的是map跟multimap安插和删除的是key/value值。
将map视为关联式数组
map提供下标操作符,支持元素的直接存取
m[key] //返回一个reference,指向键值为key的元素。如果该元素尚未存在,就安插该元素
2.map和multimap的运用实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <map> 3 #include <string> 4 using namespace std; 5 6 int main() 7 { 8 typedef map<string,float> StringFloatMap; 9 StringFloatMap stocks; 10 stocks["BASF"]=369.50; 11 stocks["VM"]=413.50; 12 stocks["Daimler"]=819.00; 13 stocks["BMW"]=834.00; 14 stocks["Siemens"]=842.20; 15 StringFloatMap::iterator pos; 16 for(pos=stocks.begin();pos!=stocks.end();++pos) 17 { 18 cout<<"stock: "<<pos->first<<"\t" 19 <<"price: "<<pos->second<<endl; 20 } 21 cout<<endl; 22 for(pos=stocks.begin();pos!=stocks.end();++pos) 23 pos->second*=2; 24 for(pos=stocks.begin();pos!=stocks.end();++pos) 25 { 26 cout<<"stock: "<<pos->first<<"\t" 27 <<"price: "<<pos->second<<endl; 28 } 29 cout<<endl; 30 stocks["Volkswagen"]=stocks["VM"]; 31 stocks.erase("VM"); 32 for(pos=stocks.begin();pos!=stocks.end();++pos) 33 { 34 cout<<"stock: "<<pos->first<<"\t" 35 <<"price: "<<pos->second<<endl; 36 } 37 cout<<endl; 38 }
下面例子展示如何将multimap当做一个字典来使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <map> 3 #include <string> 4 #include <iomanip> 5 using namespace std; 6 7 int main() 8 { 9 typedef multimap<string,string> StrStrMap; 10 StrStrMap dict; 11 dict.insert(make_pair("day","Tat")); 12 dict.insert(make_pair("strange","fremd")); 13 dict.insert(make_pair("car","Auto")); 14 dict.insert(make_pair("smart","elegant")); 15 dict.insert(make_pair("trait","Merkmak")); 16 dict.insert(make_pair("strange","seltsam")); 17 dict.insert(make_pair("smart","raffiniert")); 18 dict.insert(make_pair("smart","klug")); 19 dict.insert(make_pair("clever","raffiniert")); 20 StrStrMap::iterator pos; 21 cout.setf(ios::left,ios::adjustfield); 22 cout<<' '<<setw(10)<<"english "<<"german "<<endl; 23 cout<<setfill('-')<<setw(20)<<""<<setfill(' ')<<endl; 24 for(pos=dict.begin();pos!=dict.end();++pos) 25 { 26 cout<<' '<<setw(10)<<pos->first.c_str() 27 <<pos->second<<endl; 28 } 29 cout<<endl; 30 string word("smart"); 31 cout<<word<<":"<<endl; 32 for(pos=dict.lower_bound(word);pos!=dict.upper_bound(word);++pos) 33 cout<<" "<<pos->second<<endl; 34 word=("raffiniert"); 35 cout<<word<<":"<<endl; 36 for(pos=dict.begin();pos!=dict.end();++pos) 37 { 38 if(pos->second==word) 39 cout<<" "<<pos->first<<endl; 40 } 41 }