set和multiset都是C++标准库中的一种关联式容器,它们都会依照一定的规则对存放到其中的元素进行排序,它们俩个主要区别在于:multiset里面的元素可以重复,而set也就类似于数学中的集合,不出现重复元素。
它们在C++标准库中的定义如下:
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;
}
通过上面的模板参数,我们可以看出来,在使用这两个类时,我们可以传入三个参数:容器中的元素类型,比较器的类型(主要用于对元素进行排序),内存模型(缺省值allocator由C++标准库提供)。比较器的缺省类型为less,这是一个仿函数,以operator<对元素进行比较。
set和multiset通常由平衡二叉树实现,能够实现元素在存储时的自动排序,但是自动排序还有一个缺点就是,排序后我们不能对元素在原来位置上进行修改,那会打乱原来元素排列的正确顺序,要改变元素值我们必须先取出旧的元素,修改后,重新插入到集合中去。
set和multiset中几个比较特殊的方法:
count(e) //返回值为e的元素的个数
find(e) //返回只想元素值为e的第一个元素的迭代器,如果没有找到就返回end()
lower_bound(e) //返回第一个可插入元素的位置,也就是元素值>=e
upper_bound(e) //返回最后一个可插入元素的位置,也就是元素值>e
equal_range(e) //返回可插入元素的第一个位置和最后一个位置,也即是元素值==e的元素区间
上述函数的测试用例如下:
#include "stdafx.h"
#include <set>
#include <iostream>
using namespace std;
class setClass{
private:
int num;
public:
setClass(int val) :num(val){
}
virtual ~setClass(){}
friend ostream& operator<<(ostream& os, const setClass& sc);
friend bool operator<(const setClass& c1, const setClass& c2);
};
bool operator<(const setClass& c1, const setClass& c2){
return c1.num < c2.num;
}
ostream& operator<<(ostream& os, const setClass& sc){
os << sc.num << endl;
return os;
}
void setTest(){
multiset<setClass> sc;
sc.insert(1); //因为setClass有接受int的构造函数,这里直接传入int值会有一步自动转换
sc.insert(2);
sc.insert(3);
sc.insert(3);
sc.insert(3);
sc.insert(3);
sc.insert(4);
sc.insert(5);
sc.insert(6);
sc.insert(7);
sc.insert(8);
cout << sc.count(3) << endl; // 4
multiset<setClass>::iterator index = sc.begin();
index++;
index++;
if (index == sc.find(3)) {//true
cout << "sc.begin() + 2 == sc.find(3)" << endl;
}
multiset<setClass>::iterator index3 = index;
if (index3 == sc.lower_bound(3)){ //true sc.lower_bound(3) 返回指向第一个元素为3的向量
cout << "sc.begin() + 2 == sc.lower_bound(3)" << endl;
}
index++;
index++;
index++;
index++;
multiset<setClass>::iterator index4 = index;
if (index4 == sc.upper_bound(3)){ //true sc.upper_bound(3) 返回指向最后一个元素为3的下一个向量 元素为4
cout << "sc.begin() + 6 == sc.lower_bound(3)" << endl;
}
pair<multiset<setClass>::iterator, multiset<setClass>::iterator> retindex = sc.equal_range(3);
if ((retindex.first == index3) && (retindex.second == index4)){
cout << "equal_range返回值得上下限,分别为lower_bound, upper_bound的返回值" << endl;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
setTest();
system("pause");
return 0;
}
另外,set和multiset的安插函数的型别也不相同:
set提供的接口如下:
pair<iterator, bool> insert(const type_value& value);
iterator insert(iterator pos, const type_value& value);
multiset提供的接口如下:
iterator insert(const type_value& value);
iterator insert(iterator pos, const type_value& value);
两者返回值不同的原因,主要是因为set不允许重复元素,而multiset允许重复元素,set通过返回一个pair把一个位置迭代器指针和bool型组织起来,主要是为了,通过bool值表示插入是否成功,如果成功了说明返回的iterator中存储的元素位置为新元素的位置,如果bool为flase,说明相同值的元素已经在集合中存在,通过iterator返回,已存在的元素的位置。