简介:
所有元素都会在插入时自动被排序
本质:
set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素
1.set构造和赋值
// set构造和赋值 /* 构造: set<T> st; //默认构造函数: set(const set &st); //拷贝构造函数 赋值: set& operator=(const set &st); //重载等号操作符 */ #include <bits/stdc++.h> using namespace std; void printset(set<int> &s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int> s1; s1.insert(10); // 插入数据只有insert方式 s1.insert(30); s1.insert(40); s1.insert(20); s1.insert(30); // set里的元素自动被排序,不允许插入重复的值 printset(s1); // 10 20 30 40 // 拷贝构造 set<int> s2(s1); printset(s2); // 10 20 30 40 // 赋值 set<int> s3; s3 = s2; printset(s3); // 10 20 30 40 } int main() { test01(); } /* 总结: set容器插入数据时用insert set容器插入数据的数据会自动排序 */
2. set大小和交换
// set大小和交换 /*不支持resize size(); //返回容器中元素的数目 empty(); //判断容器是否为空 swap(st); //交换两个集合容器 */ #include <bits/stdc++.h> using namespace std; void printset(set<int> &s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int> s1; s1.insert(10); s1.insert(30); s1.insert(40); s1.insert(20); s1.insert(30); printset(s1); // 10 20 30 40 if (s1.empty()) { cout << "s1为空" << endl; } else { cout << "s1为不空" << endl; cout << s1.size() << endl; // 4 } set<int> s2; s2.insert(10); printset(s2); // 10 s1.swap(s2); printset(s1); // 10 printset(s2); // 10 20 30 40 } int main() { test01(); } /* 总结: 统计大小 — size 判断是否为空 — empty 交换容器 — swap */
3.set插入和删除
// set插入和删除 /* insert(elem); //在容器中插入元素。 clear(); //清除所有元素 erase(pos); //删除pos'迭代器'所指的元素,返回下一个元素的迭代器。 erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。 erase(elem); //删除容器中'值'为elem的元素。(类似remove) */ #include <bits/stdc++.h> using namespace std; void printset(set<int> &s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int> s1; // 插入 s1.insert(30); s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); printset(s1); // 10 20 30 40 // 删除迭代器位置 s1.erase(s1.begin()); printset(s1); // 20 30 40 // 删除元素 s1.erase(40); printset(s1); // 20 30 // 清空 s1.clear(); printset(s1); } int main() { test01(); } /* 总结: 插入 — insert 删除 — erase 清空 — clear */
4.set查找和统计
// set查找和统计 /* find(key); //查找key是否存在,若存在,返回该键的元素的'迭代器';若不存在,返回'set.end()'; count(key); //统计key的'元素'个数 set中返回0/1 multiset为0/>0的值 */ #include <bits/stdc++.h> using namespace std; void printset(set<int> &s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { set<int> s1; // 插入 s1.insert(30); s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); printset(s1); // 10 20 30 40 // 查找 set<int>::iterator pos = s1.find(40); if (pos != s1.end()) { cout << "找到元素:" << *pos << endl; // 找到元素:40 } else { cout << "未找到元素:" << endl; } // 统计 int num = s1.count(30); // 统计30的个数 cout << num << endl; // 1 } int main() { test01(); } /* 总结: 查找 — find (返回的是迭代器) 统计 — count (对于set,结果为0或者1) */
5.set和multiset区别
// set和multiset区别 /* 区别: set不可以插入重复数据,而multiset可以 set插入数据的同时会返回插入结果,表示插入是否成功 multiset不会检测数据,因此可以插入重复数据 */ #include <bits/stdc++.h> using namespace std; void test01() { set<int> s; // set插入 pair<set<int>::iterator, bool> ret = s.insert(10); if (ret.second) { cout << "第一次插入成功" << endl; // √ } else { cout << "第一次插入失败" << endl; // × } // set重复插入 ret = s.insert(10); if (ret.second) { cout << "第二次插入成功" << endl; // × } else { cout << "第二次插入失败" << endl; // √ } multiset<int> s2; // multiset插入 s2.insert(10); // multiset重复插入 s2.insert(10); for (multiset<int>::iterator it = s2.begin(); it != s2.end(); it++) { cout << *it << " "; // 10 10 } } int main() { test01(); } /* 总结: 如果不允许插入重复数据可以利用set 如果需要插入重复数据利用multiset */
6. pair对组创建
// pair对组创建 /* 两种创建方式: pair<type, type> p ( value1, value2 ); pair<type, type> p = make_pair( value1, value2 ); */ #include <bits/stdc++.h> using namespace std; void test01() { pair<string, int> p("Tom", 20); cout << p.first << " " << p.second << endl; // Tom 20 pair<string, int> p2 = make_pair("Jerry", 15); cout << p2.first << " " << p2.second << endl; // Jerry 15 } int main() { test01(); } /* 总结: 两种方式都可以创建对组,记住一种即可 */
7.1 set容器排序
示例一 set存放内置数据类型
// set容器排序 /* 学习目标: set容器默认排序规则为从小到大,掌握如何改变排序规则 主要技术点: 利用仿函数,可以改变排序规则 */ // 示例一 set存放内置数据类型 #include <bits/stdc++.h> using namespace std; class cmp // 仿函数(类) { public: bool operator()(int v1, int v2) { return v1 > v2; } }; void test01() { // 升序 set<int> s1; s1.insert(10); s1.insert(30); s1.insert(20); s1.insert(50); s1.insert(40); for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; // 10 20 30 40 50 } cout << endl; // 降序,在创建容器时就指定排序规则 set<int, cmp> s2; s2.insert(10); s2.insert(30); s2.insert(20); s2.insert(50); s2.insert(40); for (set<int, cmp>::iterator it = s2.begin(); it != s2.end(); it++) { cout << *it << " "; // 50 40 30 20 10 } cout << endl; } int main() { test01(); } /* 总结: 对于自定义数据类型,set必须指定排序规则才可以插入数据 */
7.2 set容器排序
示例二 set存放自定义数据类型
// set容器排序 // 示例二 set存放自定义数据类型 #include <bits/stdc++.h> using namespace std; class person { public: person(string name, int age) { this->name = name; this->age = age; } string name; int age; }; class cmp { public: bool operator()(person p1, person p2) { // 按年龄降序 return p1.age > p2.age; } }; void test01() { /// 自定义的类型 都会指定排序类型 set<person, cmp> s; person s1("刘备", 24); person s2("关羽", 28); person s3("张飞", 25); person s4("赵云", 21); s.insert(s1); s.insert(s2); s.insert(s3); s.insert(s4); for (set<person, cmp>::iterator it = s.begin(); it != s.end(); it++) { cout << (*it).name << " " << (*it).age; /* 关羽 28 张飞 25 刘备 24 赵云 21 */ cout << endl; } } int main() { test01(); } /* 总结: 对于自定义数据类型,set必须指定排序规则才可以插入数据 */