STL学习笔记----5.容器 set 和 multiset

来源:互联网 发布:网络教育招生 编辑:程序博客网 时间:2024/05/22 03:32
一. Set 的特点

Set 和 multiset 会根据特定的排序准则,自动将元素排序。两者不同处在于multiset允许元素重复set不允许重复

优点:

搜索元素时具有良好的性能。

限制:

不能直接改变元素值,因为这样会打乱原本正确的顺序,因此要改变元素值,必须先删除旧元素,再插入新元素。


Set 和 multiset 通常以平衡二叉树来实现,如下图:


二. 排序准则

Set<Elem, op>,其中op为排序准则,缺省准则是less,即从小到大排序。

[cpp] view plaincopy
  1. std::set<int, std::greater<int> > coll;  //从大到小  
  2. std::set<int, std::less<int> > coll;    //从小到大  
  3.   
  4. std::set<int> coll; //默认less<>,也是从小到大   

三. 搜索函数

由于 set 和 multiset 在元素快速搜索方面有优化设计,所以提供了特殊的搜索函数:

[cpp] view plaincopy
  1. //返回元素值为elem的元素个数  
  2. s.count(elem)  
  3.   
  4. //返回第一个元素值为 elem 的位置,找不到的话返回end()  
  5. s.find(elem)  
  6.   
  7. //返回 elem 的第一个可以安插的位置,也就是 (元素值 >=elem)的位置  
  8. s.lower_bound(elem)  
  9.   
  10. //返回 elem 的最后一个可以安插的位置,也就是(元素值 > elem)的位置  
  11. s.upper_bound(elem)  
  12.   
  13. //返回 elem 可以安插的第一个位置和最后一个位置,也就是(元素值 == elem) 的元素区间  
  14. s.equal_range(elem)  

四. 插入和删除函数

[cpp] view plaincopy
  1. //插入elem元素,返回新元素的位置,pos 指出插入操作的搜寻起点,如果 pos 恰当可以加快速度  
  2. c.insert(pos,elem)  
  3. c.insert(elem)  
  4.       
  5.   
  6. //删除与elem相等的元素,返回删除元素的个数  
  7. c.erase(elem)  
  8.   
  9. c.erase(pos)  
  10. c.erase(beg, end)  

注意插入操作的返回值:

因为 set 不允许重复,面 multiset 允许重复,所以他们的 insert 操作有不有同的返回值。

[cpp] view plaincopy
  1. //set 提供的接口  
  2. pair<iterator, bool> insert(const value_type& elem); //返回 pair<>  

因为 set 不允许元素重复,所以如果插入相同的元素,将会返回失败

Pari 的 secode 成员表示插入是否成功。

Pair 的 first 成员返回新元素的位置。

[cpp] view plaincopy
  1. //multiset 提供的接口  
  2. iterator            insert(const value_type& elem); //返回新元素的位置  

注意删除操作:

[cpp] view plaincopy
  1. //删除与 elem 相等的元素,返回删除元素的个数  
  2. c.erase(elem)  
我们可以看到,其它容器的 erase() 操作参数都是位置。而set 除了其它几个erase(),还有这个传入值的 erase() 函数操作。这个操作在 list 里应该对应的是,c.remove()。但是这里确没有一至,可能是历史原因吧,我也不知道,但是这个要注意。反正我们记住,在 set 里有一个 erase(elem),在 list 里有一个 remove()  操作就行了。

如果 multisets 内含有重复元素,你不能使用 erase(),来删除这些重复元素中的第一个,你可以这么做:

[cpp] view plaincopy
  1. std::multiset<Elem> coll;  
  2. ...  
  3.   
  4. //remove first element with passed value  
  5. std::multiset<Elem>::iterator pos;  
  6. pos = coll.find (elem);  
  7. if (pos != coll.end())   
  8. {  
  9.     coll.erase(pos);  
  10. }  

五. 示例代码

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <set>  
  3. using namespace std;  
  4.   
  5. int main()  
  6. {  
  7.       
  8. /*type of the collection: 
  9. *-no duplicates 
  10. *-elements are integral values 
  11. *-descending order 
  12. */  
  13.     typedef set<int,greater<int> > IntSet;  
  14.       
  15.     IntSet coll1;         // empty set container  
  16.       
  17.     //insert elements in random order  
  18.     coll1.insert(4);  
  19.     coll1.insert(3);  
  20.     coll1.insert(5);  
  21.     coll1.insert(1);  
  22.     coll1.insert(6);  
  23.     coll1.insert(2);  
  24.     coll1.insert(5);  
  25.       
  26.     //iterate over all elements and print them  
  27.     IntSet::iterator pos;  
  28.     for (pos = coll1.begin(); pos != coll1.end(); ++pos) {  
  29.         cout << *pos << ' ';  
  30.     }  
  31.     cout << endl;  
  32.       
  33.     //再次插入 4  
  34.     pair<IntSet::iterator, bool> status = coll1.insert(4);  
  35.     if (status.second) {  
  36.         cout << "4 inserted as element "  
  37.             << distance (coll1.begin(),status. first) + 1  
  38.             << endl;  
  39.     }  
  40.     else {  
  41.         cout << "4 already exists" << endl;  
  42.     }  
  43.       
  44.     //assign elements to another set with ascending order  
  45.     set<int> coll2(coll1.begin(),  
  46.         coll1.end());  
  47.       
  48.     //print all elements of the copy  
  49.     copy (coll2.begin(), coll2.end(),  
  50.         ostream_iterator<int>(cout," "));  
  51.     cout << endl;  
  52.       
  53.     //remove all elements up to element with value 3  
  54.     coll2.erase (coll2.begin(), coll2.find(3));  
  55.       
  56.     //remove all elements with value 5  
  57.     int num;  
  58.     num = coll2.erase (5);  
  59.     cout << num << " element(s) removed" << endl;  
  60.       
  61.     //print all elements  
  62.     copy (coll2.begin(), coll2.end(),  
  63.         ostream_iterator<int>(cout," "));  
  64.     cout << endl;  
  65.   
  66.     return 0;  
  67. }