一. Set 的特点
Set 和 multiset 会根据特定的排序准则,自动将元素排序。两者不同处在于multiset允许元素重复而set不允许重复。
优点:
在搜索元素时具有良好的性能。
限制:
你不能直接改变元素值,因为这样会打乱原本正确的顺序,因此要改变元素值,必须先删除旧元素,再插入新元素。
Set 和 multiset 通常以平衡二叉树来实现,如下图:
二. 排序准则
Set<Elem, op>,其中op为排序准则,缺省准则是less,即从小到大排序。
- std::set<int, std::greater<int> > coll; //从大到小
- std::set<int, std::less<int> > coll; //从小到大
- std::set<int> coll; //默认less<>,也是从小到大
三. 搜索函数
由于 set 和 multiset 在元素快速搜索方面有优化设计,所以提供了特殊的搜索函数:- //返回元素值为elem的元素个数
- s.count(elem)
- //返回第一个元素值为 elem 的位置,找不到的话返回end()
- s.find(elem)
- //返回 elem 的第一个可以安插的位置,也就是 (元素值 >=elem)的位置
- s.lower_bound(elem)
- //返回 elem 的最后一个可以安插的位置,也就是(元素值 > elem)的位置
- s.upper_bound(elem)
- //返回 elem 可以安插的第一个位置和最后一个位置,也就是(元素值 == elem) 的元素区间
- s.equal_range(elem)
四. 插入和删除函数
- //插入elem元素,返回新元素的位置,pos 指出插入操作的搜寻起点,如果 pos 恰当可以加快速度
- c.insert(pos,elem)
- c.insert(elem)
- //删除与elem相等的元素,返回删除元素的个数
- c.erase(elem)
- c.erase(pos)
- c.erase(beg, end)
注意插入操作的返回值:
因为 set 不允许重复,面 multiset 允许重复,所以他们的 insert 操作有不有同的返回值。
- //set 提供的接口
- pair<iterator, bool> insert(const value_type& elem); //返回 pair<>
因为 set 不允许元素重复,所以如果插入相同的元素,将会返回失败。
Pari 的 secode 成员表示插入是否成功。
Pair 的 first 成员返回新元素的位置。
- //multiset 提供的接口
- iterator insert(const value_type& elem); //返回新元素的位置
注意删除操作:
- //删除与 elem 相等的元素,返回删除元素的个数
- c.erase(elem)
如果 multisets 内含有重复元素,你不能使用 erase(),来删除这些重复元素中的第一个,你可以这么做:
- std::multiset<Elem> coll;
- ...
- //remove first element with passed value
- std::multiset<Elem>::iterator pos;
- pos = coll.find (elem);
- if (pos != coll.end())
- {
- coll.erase(pos);
- }
五. 示例代码
- #include <iostream>
- #include <set>
- using namespace std;
- int main()
- {
- /*type of the collection:
- *-no duplicates
- *-elements are integral values
- *-descending order
- */
- typedef set<int,greater<int> > IntSet;
- IntSet coll1; // empty set container
- //insert elements in random order
- coll1.insert(4);
- coll1.insert(3);
- coll1.insert(5);
- coll1.insert(1);
- coll1.insert(6);
- coll1.insert(2);
- coll1.insert(5);
- //iterate over all elements and print them
- IntSet::iterator pos;
- for (pos = coll1.begin(); pos != coll1.end(); ++pos) {
- cout << *pos << ' ';
- }
- cout << endl;
- //再次插入 4
- pair<IntSet::iterator, bool> status = coll1.insert(4);
- if (status.second) {
- cout << "4 inserted as element "
- << distance (coll1.begin(),status. first) + 1
- << endl;
- }
- else {
- cout << "4 already exists" << endl;
- }
- //assign elements to another set with ascending order
- set<int> coll2(coll1.begin(),
- coll1.end());
- //print all elements of the copy
- copy (coll2.begin(), coll2.end(),
- ostream_iterator<int>(cout," "));
- cout << endl;
- //remove all elements up to element with value 3
- coll2.erase (coll2.begin(), coll2.find(3));
- //remove all elements with value 5
- int num;
- num = coll2.erase (5);
- cout << num << " element(s) removed" << endl;
- //print all elements
- copy (coll2.begin(), coll2.end(),
- ostream_iterator<int>(cout," "));
- cout << endl;
- return 0;
- }