C++提高编程 3 STL常用容器 -set/multiset容器
3.8 set/multiset容器
3.8.1 set基本概念
简介:所有元素都会在插入时自动被排序
本质:set/multiset属于关联式容器,底层结构是用二叉树实现
set和multiset区别:
set不允许容器中有重复的元素
multiset允许容器中有重复元素
3.8.2 set构造与赋值
功能描述:创建set容器以及赋值
构造:
set<T> st; //默认构造函数
set(const set &st); //拷贝构造函数
赋值:
set& operator=(const set &st);//重载等号操作符
set:
#include<iostream> #include<set> using namespace std; #include<string> //set容器构造和赋值 void printSet(set<int>&s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { set<int>s1; //插入数据只有insert方式 s1.insert(30); s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); //遍历容器 //set特点:1、所有元素再插入的时候会自动排序 2、不允许插入重复值 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() { test1(); system("pause"); return 0; }
multiset:
#include<iostream> #include<set> using namespace std; #include<string> //multiset容器构造和赋值 void printmultiSet(multiset<int>&s) { for (multiset<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { multiset<int>s1; //插入数据只有insert方式 s1.insert(30); s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); //遍历容器 //set特点:1、所有元素再插入的时候会自动排序 2、不允许插入重复值 printmultiSet(s1); //10 20 30 30 40 //拷贝构造 multiset<int>s2(s1); printmultiSet(s2); //10 20 30 30 40 //赋值 multiset<int>s3; s3 = s2; printmultiSet(s3); //10 20 30 30 40 } int main() { test1(); system("pause"); return 0; }
3.8.3 set大小和交换
功能描述:
统计set容器大小以及交换set容器
函数原型:
size(); //返回容器中元素个数
empty(); //判断容器是否为空
swap(); //交换两个集合容器
#include<iostream> #include<set> using namespace std; //set容器大小和交换 void printSet(set<int>&s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } //大小 void test1() { set<int>s1; s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); if (s1.empty()) { cout << "set s1容器为空" << endl; } else { cout << "set s1容器不为空" << endl; printSet(s1); //10 20 30 40 cout << "s1的大小为:" << s1.size() << endl; //s1的大小为:4 } } //交换 void test2() { set<int>s1; s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(30); set<int>s2; s2.insert(50); s2.insert(70); s2.insert(60); s2.insert(80); cout << "交换前:" << endl; printSet(s1); //10 20 30 40 printSet(s2); //50 60 70 80 cout << "交换后:" << endl; s1.swap(s2); printSet(s1); //50 60 70 80 printSet(s2); //10 20 30 40 } int main() { test1(); test2(); system("pause"); return 0; }
3.8.4 set插入和删除
功能描述:set容器进行插入数据和删除数据
函数原型:
insert(elem); //在容器中插入元素
clear(); //清除所有元素
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg,end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem); //删除容器中值为elem的元素
#include<iostream> using namespace std; #include<set> //set容器 插入与删除 void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { set<int>s; //插入 s.insert(20); s.insert(10); s.insert(30); s.insert(50); s.insert(40); printSet(s); //10 20 30 40 50 //删除 s.erase(s.begin()); printSet(s); //20 30 40 50 s.erase(30); printSet(s); //20 40 50 s.erase(s.begin(),s.end()); printSet(s); //打印一行空白 s.clear(); printSet(s); //打印一行空白 } int main() { test1(); system("pause"); return 0; }
3.8.5 set查找与统计
功能描述:对set容器进行查找数据以及统计数据
函数原型:
find(key); //查找key是否存在,若存在,返回该键的迭代器;若不存在,返回set.end();
count(key); //统计key的元素个数 //对set而言,统计元素的个数的结果,要么是0,要么是1。但multiset可以统计真实个数
set:
#include<iostream> using namespace std; #include<set> //set容器 插入与删除 void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { set<int>s; //插入 s.insert(30); s.insert(20); s.insert(30); s.insert(10); s.insert(30); s.insert(50); s.insert(30); s.insert(40); s.insert(30); printSet(s); //10 20 30 40 50 //cout << "set容器中30的数量:" << s.find(30) << endl; //想法错了 set<int>::iterator pos = s.find(50); if (pos != s.end()) { cout << "找到元素:" << *pos << endl; } else { cout << "未找到元素!" << endl; } } //统计 void test2() { set<int>s; //插入 s.insert(30); s.insert(20); s.insert(30); s.insert(10); s.insert(30); s.insert(50); s.insert(30); s.insert(40); s.insert(30); printSet(s); //10 20 30 40 50 int num = s.count(30); //对set而言,统计元素的个数的结果,要么是0,要么是1 cout << "所要统计的元素个数为:" << num << endl; //num = 1 } int main() { test1(); test2(); system("pause"); return 0; }
multiset:
#include<iostream> using namespace std; #include<set> //multiset容器 插入与删除 void printMultiet(multiset<int>& s) { for (multiset<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { multiset<int>s; //插入 s.insert(30); s.insert(20); s.insert(30); s.insert(10); s.insert(30); s.insert(50); s.insert(30); s.insert(40); s.insert(30); printMultiet(s); //10 20 30 30 30 30 30 40 50 //cout << "set容器中30的数量:" << s.find(30) << endl; //想法错了 multiset<int>::iterator pos = s.find(50); if (pos != s.end()) { cout << "找到元素:" << *pos << endl; } else { cout << "未找到元素!" << endl; } } //统计 void test2() { multiset<int>s; //插入 s.insert(30); s.insert(20); s.insert(30); s.insert(10); s.insert(30); s.insert(50); s.insert(30); s.insert(40); s.insert(30); printMultiet(s); //10 20 30 30 30 30 30 40 50 int num = s.count(30); //对multiset而言,统计元素的个数的结果是真实的个数 cout << "所要统计的元素个数为:" << num << endl; //num = 5 } int main() { test1(); test2(); system("pause"); return 0; }
3.8.6 set和multiset区别
区别:
1、set不可以插入重复数据,而multiset可以;
2、set插入数据的同时会返回插入结果,表示插入是否成功
3、multiset不会检测数据,因此可以插入重复数据
总结:如果不允许插入重复数据就用set,如果需要插入重复的数据就要用multiset;
#include<iostream> using namespace std; #include<set> //set容器与multiset容器区别 void printSet(set<int>& s) { for (set<int>::iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test1() { set<int>s; //不允许插入重复值 pair<set<int>::iterator, bool>ret = s.insert(10); if (ret.second) //ret的第二个参数 即bool为真,表示插入成功 { cout << "第1次插入成功!" << endl; //第1次插入成功! } else { cout << "第1次插入失败!" << endl; } ret = s.insert(10); //再插一次10 if (ret.second) { cout << "第2次插入成功!" << endl; } else { cout << "第2次插入失败!" << endl; //第2次插入失败! } multiset<int>ms; //允许插入重复值 ms.insert(10); ms.insert(10); ms.insert(10); ms.insert(10); for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) { cout << *it << " "; //10 10 10 10 } cout << endl; } int main() { test1(); system("pause"); return 0; }
3.8.7 set容器排序
学习目标:set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点:利用仿函数,可以改变排序规则
改变默认数据类型规则
#include<iostream> using namespace std; #include<string> #include<set> //set容器排序 class myCompare //构建仿函数 { public: bool operator()(const int& v1,const int& v2) const //第一个小括号是operator()自带的重载符号,第二个小括号是重载函数的参数列表 { return v1 > v2; } }; void test1() { set<int>s1; s1.insert(20); s1.insert(10); s1.insert(30); 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, myCompare>s2; //仿函数本质上是一个类型,可以指定仿函数为类型,进行插入 s2.insert(20); s2.insert(10); s2.insert(30); s2.insert(50); s2.insert(40); for (set<int, myCompare>::const_iterator it = s2.begin(); it != s2.end(); it++) { cout << *it << " "; //50 40 30 20 10 } cout << endl; } int main() { test1(); system("pause"); return 0; }
改变自定义数据类型排序:
#include<iostream> using namespace std; #include<string> #include<set> //set容器排序 存放自定义数据类型 class Person { public: Person(string name, int age) { this->m_Age = age; this->m_Name = name; } string m_Name; int m_Age; }; class comparePerson { public: bool operator()(const Person& p1, const Person& p2) const { //按照年龄降序 return p1.m_Age > p2.m_Age; } }; void test1() { //自定义数据类型 都会指定排序规则 set<Person, comparePerson>s; Person p1("刘备", 24); Person p2("曹操", 25); Person p3("关羽", 27); Person p4("张飞", 28); s.insert(p1); s.insert(p2); s.insert(p3); s.insert(p4); for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++) { cout << "姓名:" << it->m_Name << " " << "年龄:" << it->m_Age << endl; } } int main() { test1(); system("pause"); return 0; }
打印结果:
姓名:张飞 年龄:28
姓名:关羽 年龄:27
姓名:曹操 年龄:25
姓名:刘备 年龄:24
总结:自定义数据类型,需要定义排序规则才能排序

浙公网安备 33010602011771号