一.特性

  1. 关联容器。
  2. 所以元素会根据元素的值自动进行排序。set是以RB-tree(红黑树是平衡二叉树的一种)为底层机制,其查找效率非常好。set容器不允许重复元素,multiset允许重复元素。
  3. 只有insert()方法。
  4. 不能用迭代器改变元素值,因为set集合值是有顺序的,改变值,会改变规则。
  5. 如果要改变元素值,必须先删除该结点,然后再插入。

set唯一性和排序性测试:

set<int> st;
st.insert(7);
st.insert(6);
st.insert(4);
st.insert(5);
st.insert(2);
st.insert(3);
st.insert(1);
st.insert(2);
st.insert(1);
st.insert(7);
for (int v : st) {
	cout << v << " ";
}

set 容器 set容器可以重复吗_c++

二.构造函数

set<int> st;//set默认
multiset<int> mt;//multiset构造函数
set(const set & st);//拷贝构造函数

三.赋值操作

set& operator=(const set & st);//重载等号操作符
set<int> st, st1;
st.swap(st1);//交换两个集合容器

四.大小操作

set<int> st;
st.size();//返回容器中元素数目
st.empty();//判断容器是否为空

五.插入和删除

set<int> st;
st.insert(num);//在容器中插入元素
st.clear();//清楚所有元素
st.erase(pos);//删除pos迭代器所指向的元素,返回下一个元素的迭代器
st.erase(beg, end);//删除区间[beg,end)所有元素,返回下一个元素迭代器
st.erase(elem);//删除容器中值为elem的元素

六.查找操作

set<int> st;
st.find(key);//查找key是否存在,若存在,返回该键的元素迭代器,若不存在,返回map.end()
st.lower_bound(keyelem);//返回第一个key>=keyelem元素的迭代器
st.upper_bound(keyelem);//返回第一个key>keyelem元素的迭代器
st.equal_range(keyelem);//返回容器key与keyelem相等的上下限的两个迭代器

测试:

set<int> st;
st.insert(7);
st.insert(6);
st.insert(4);
st.insert(5);
st.insert(2);
st.insert(3);
st.insert(1);
st.insert(2);
st.insert(1);
st.insert(7);
for (int v : st) {
	cout << v << " ";
}
cout << endl;
cout << "--------测试find()------" << endl;
set<int>::iterator it1 = st.find(4);
if (it1 == st.end()) {
	cout << "没找到!" << endl;
}
else {
	cout << "it1=" << *it1 << endl;
}
cout << "--------测试lower_bound(keyelem)()------" << endl;
set<int>::iterator it2 = st.lower_bound(4);
cout << "it2=" << *it2 << endl;
cout << "--------测试upper_bound(keyelem)()------" << endl;
set<int>::iterator it3 = st.upper_bound(4);
cout << "it3=" << *it3 << endl;
cout << "--------测试equal_range(keyelem)()------" << endl;
pair<set<int>::iterator,set<int>::iterator> mypair = st.equal_range(4);
if (mypair.first == st.end()) {
	cout << "没有找到!" << endl;
}
else {
	cout << *(mypair.first) << endl;
}
if (mypair.second == st.end()) {
	cout << "没有找到!" << endl;
}
else {
	cout << *(mypair.second) << endl;
}

结果:

set 容器 set容器可以重复吗_迭代器_02

七.更改默认排序

使用仿函数。
一定要注意仿函数书写!!!要加const
例子1:

仿函数
class mycompare {
public:
	bool operator()(const int& v1,const int& v2) const{
		return v1 > v2;
	}
};
void test02() {
	set<int,mycompare> st;//注意这里
	st.insert(7);
	st.insert(6);
	st.insert(4);
	st.insert(5);
	st.insert(2);
	st.insert(3);
	st.insert(1);
	st.insert(2);
	st.insert(1);
	st.insert(7);
	for (int v : st) {
		cout << v << " ";
	}
}

结果:

set 容器 set容器可以重复吗_迭代器_03


例子2:

class Person {
public:
	int id;
	int age;
	Person(int id,int age):id(id),age(age) {}
};
//仿函数
class mycompare2 {
public:
	bool operator()(const Person& p1,const Person& p2) const{
		return p1.age > p2.age;
	}
};
void test03() {
	set<Person, mycompare2> sp;
	Person p1(10, 20), p2(30, 40), p3(50, 60);
	sp.insert(p1);
	sp.insert(p2);
	sp.insert(p3);
	//遍历方法一:
	for (Person v : sp) {
		cout << "age=" << v.age << ",id=" << v.id << endl;
	}
	//遍历方法二:
	
}

结果:

set 容器 set容器可以重复吗_运维_04

八.查找问题

还是上面的代码:
由于set是按照age排序,因此,执行find()函数也是查找age。
在此,我们定义Person p4(30, 20),然后执行sp.find(p4)查看查找结果。

set<Person, mycompare2> sp;
	Person p1(10, 20), p2(30, 40), p3(50, 60);
	sp.insert(p1);
	sp.insert(p2);
	sp.insert(p3);
	//查找
	Person p4(30, 20);
	set<Person, mycompare2>::iterator it = sp.find(p4);
	if (it == sp.end() ) {
		cout << "不存在!" << endl;
	}
	else {
		cout << "age=" << (*it).age << ",id=" << (*it).id << endl;
	}

结果:发现查找出来的是p1的值,但是应该显示不存在才对。

set 容器 set容器可以重复吗_迭代器_05


原因:p4虽然不存在set中,但是p4.age=p1.age,所以自然查到p1的值。