set和multiset会根据特定的排序准则排序,自动将元素进行排序,不同之处在于multiset允许元素重复而set不允许。
其声明如下
namespace std
{
template<class T, class Compare = less<T>, class Allocator = allocator<T> >
class set;
template<class T, class Compare = less<T>, class Allocator = allocator<T> >
class multiset;
}
如果没有传入特别的排序准则,就采用缺省的准则less-这是一个仿函数,以operator < 对元素进行比较。
sets和multisets通常以平衡二叉树(红黑树)完成(见下图),自动排序的主要优点在于其搜寻算法具有对数复杂度。但是也造成个限制你不能直接改变元素值,因为这会打乱原本正确的顺序。因此要改变元素值,必须先删除就元素,再插入新元素
元素的比较动作只能比较型别相同(元素和排序准则都必须相同)的元素
equal_range则是将lower_bound()和upper_bound()的返回值做成一个pair返回,所以它返回的是“与参数值相等”的元素所形成的区间,如果lower_bound()或“equal_range()的第一值”等于“equal_range()的第二值”或upper_bound(),则此set或multiset内部存在相同的数值。见下面例子
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;
int main(void)
{
set<int> col;
col.insert(1);
col.insert(2);
col.insert(4);
col.insert(5);
col.insert(6);
cout << "lower_bound(3): " << *col.lower_bound(3) << endl; // 4
cout << "upper_bound(3): " << *col.upper_bound(3) << endl; // 4
cout << "equal_range(3): " << *col.equal_range(3).first << " "<< *col.equal_range(3).second << endl;// 4 4
cout << endl;
cout << "lower_bound(5): " << *col.lower_bound(5) << endl;//5
cout << "upper_bound(5): " << *col.upper_bound(5) << endl;//6
cout << "equal_range(5): " << *col.equal_range(5).first << " "
<< *col.equal_range(5).second << endl;//5 6
return 0;
}
注意这里的迭代器是双向迭代器,对于只能用于随机迭代器的STL算法来说,就不能使用了,也不能对其调用任何变动性算法,如remove。
/* pair结构中的second表示安插是否成功,first成员返回新元素的位置,或返回现存的同值元素的位置。 */
pair<iterator,bool> insert(const value_type& elem);
iterator insert(iterator pos_hint,const value_type& elem);
因此可以如下使用
set<double> c;
if (c.insert(3.3).second)
{
cout << "3.3 inserted " << endl;
}
else
{
cout << "3.3 already exits " << endl;
}
multisets提供以下接口
iterator insert(const value_type& elem);
iterator insert(iterator pos_hint,const value_type& elem);
返回值型别的不同是因为set不允许重复,而multisets允许重复,因此如果将某元素安插至一个set内,而该set已经内含同值元素,则安插失败。
#include <set>
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
int main(void)
{
typedef set<int,greater<int> > IntSet;
IntSet col1;
col1.insert(4);
col1.insert(3);
col1.insert(5);
col1.insert(1);
col1.insert(6);
col1.insert(2);
col1.insert(5);
IntSet::iterator pos;
for (pos=col1.begin(); pos!=col1.end(); ++pos)
{
cout << *pos << endl; //6 5 4 3 2 1
}
cout << endl;
//插入4
pair<IntSet::iterator,bool> status = col1.insert(4);
if (status.second)
{
cout << "4 inserted as element"
<< distance(col1.begin(),status.first) + 1
<< endl;
}
else
{
cout << "4 already exits" << endl; //打印
}
set<int> col2(col1.begin(),col1.end());
copy(col2.begin(),col2.end(),ostream_iterator<int>(cout," ")); // 1 2 3 4 5 6
cout << endl;
//移除3
col2.erase(col2.begin(),col2.find(3)); // 3 4 5 6注意3没被移除,一般区间处理都是左闭右开
int num;
num = col2.erase(5);
cout << num << " element(s) removed" << endl; //3 4 6
copy(col2.begin(),col2.end(),ostream_iterator<int>(cout," ")); //3 4 6
cout << endl;
return 0;
}
对于multisets,上诉程序如下
#include <set>
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
int main(void)
{
typedef multiset<int,greater<int> > IntSet;
IntSet col1;
col1.insert(4);
col1.insert(3);
col1.insert(5);
col1.insert(1);
col1.insert(6);
col1.insert(2);
col1.insert(5);
IntSet::iterator pos;
for (pos=col1.begin(); pos!=col1.end(); ++pos)
{
cout << *pos << endl; //6 5 5 4 3 2 1
}
cout << endl;
//插入4
IntSet::iterator ipos = col1.insert(4); //insert返回新元素的位置
cout << "4 inserted as element"
<< distance(col1.begin(),ipos) + 1 << endl; //5
multiset<int> col2(col1.begin(),col1.end());
copy(col2.begin(),col2.end(),ostream_iterator<int>(cout," ")); // 1 2 3 4 4 5 5 6
cout << endl;
//移除3
col2.erase(col2.begin(),col2.find(3)); // 3 4 4 5 5 6
int num;
num = col2.erase(5);
cout << num << " element(s) removed" << endl; //2
copy(col2.begin(),col2.end(),ostream_iterator<int>(cout," ")); //3 4 4 6
cout << endl;
return 0;
}