重新系统学习c++语言,并将学习过程中的知识在这里抄录、总结、沉淀。同时希望对刷到的朋友有所帮助,一起加油哦!
每一次学习都是为了追求智慧!
写在前面,本篇章主要介绍STL中常用容器set/multiset。
1.1 set基本概念
本质:
set和multiset,属于关联式容器,底层结构是用二叉树实现的。
特性:
所有元素都会在插入时自动被排序。
set和multiset区别:
- set 不允许容器内有重复元素,可重复插入元,但只保存一份。
- multiset 允许容器内有重复元素。
1.2 set构造和赋值
构造函数:
set<T> st; /
/默认构造函数:set(const set &st);
//拷贝构造函数
赋值:
set& operator=(const set &st);
//重载等号操作符
示例:
#include <iostream>
#include <string>
#include<set>
using namespace std;
void printSet(const set<int>& s) {
for (auto item : s) {
cout << item << " ";
}
cout << endl;
}
void test() {
set<int> s;
// set插入数据只有insert方式
s.insert(2);
s.insert(4);
s.insert(2);
s.insert(3);
s.insert(1);
// 不能插入重复的值,就算重复插入,也只保留一份数据
// 元素在插入时自动被排序,默认按照升序
printSet(s);
// 拷贝构造函数
set<int> s2(s);
printSet(s2);
//赋值
set<int> s3;
s3 = s2;
printSet(s3);
}
int main() {
test();
system("pause");
return 0;
}
1.3 set大小和交互
函数原型:
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器
示例:
#include <iostream>
#include <string>
#include<set>
using namespace std;
//size(); //返回容器中元素的数目
//empty(); //判断容器是否为空
//swap(st); //交换两个集合容器
void printSet(const set<int>& s) {
for (auto item : s) {
cout << item << " ";
}
cout << endl;
}
void test() {
set<int> s;
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
printSet(s);
if (s.empty()) {
cout << "s is empty" << endl;
}
else {
cout << "s is not empty" << endl;
cout << "s size:" << s.size() << endl;
}
set<int> s2;
s2.insert(10);
s2.insert(30);
s2.insert(20);
printSet(s2);
cout << "change s and s2:" << endl;
s.swap(s2);
printSet(s);
printSet(s2);
}
int main() {
test();
system("pause");
return 0;
}
1.4 set插入和删除
函数原型:
- insert(elem); //在容器中插入元素。
- clear(); //清除所有元素
- erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
- erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
- erase(elem); //删除容器中值为elem的元素。
示例:
#include <iostream>
#include <string>
#include<set>
using namespace std;
void printSet(const set<int>& s) {
for (set<int>::const_iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test() {
set<int> s;
s.insert(2);
s.insert(1);
s.insert(3);
s.insert(4);
s.insert(5);
printSet(s);
//erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
set<int>::const_iterator it = s.erase(s.begin());
cout << *it << endl;// 返回下一个元素的迭代器 元素值2
printSet(s);
//erase(elem); //删除容器中值为elem的元素。
s.erase(2);
printSet(s);
set<int> s2(s);
//erase(beg, end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
s.erase(s.begin(), s.end());
printSet(s);
cout << "s2:" << endl;
printSet(s2);
//clear(); //清除所有元素
s2.clear();
cout << "s2 after clear:" << endl;
printSet(s2);
}
int main() {
test();
system("pause");
return 0;
}
1.5 set查找和统计
函数原型:
- find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
- count(key); //统计key的元素个数。set 只会返回0和1,multiset是0和n。
示例:
#include <iostream>
#include <string>
#include<set>
using namespace std;
void test() {
set<int> s;
s.insert(2);
s.insert(2);
s.insert(1);
s.insert(3);
s.insert(4);
s.insert(5);
//find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
set<int>::iterator pos = s.find(2);
if (pos != s.end()) {
cout << "finded:" << *pos << endl;
}
else {
cout << "not find" << endl;
}
//count(key); //统计key的元素个数
int n = s.count(2);
cout << "s中2的个数:" << n << endl;
n = s.count(9);
cout << "s中9的个数:" << n << endl;
}
int main() {
test();
system("pause");
return 0;
}
1.6 set和multiset区别
区别:
(1) 能否插入重复数据:
se不可以,multiset可以;
(2) 插入数据后返回插入成功失败结果:
set 返回;multiset不返回,所以可以插入重复数据。
示例:
#include <iostream>
#include <string>
#include<set>
using namespace std;
// set 和multiset区别
template<class T>
void myPrint(T& s) {
for (auto item : s) {
cout << item << " ";
}
cout << endl;
}
void test() {
set<int> s;
pair<set<int>::iterator, bool> ret=s.insert(1);
if (ret.second) {
cout << "第一次插入成功" << endl;
}
else {
cout << "第一次插入失败" << endl;
}
ret = s.insert(1);
if (ret.second) {
cout << "第二次插入成功" << endl;
}
else {
cout << "第二次插入失败" << endl;
}
myPrint(s);
}
// multiset 会插入重复数据,并且在插入时也会做好排序
void test2() {
multiset<int> ms;
ms.insert(4);
ms.insert(2);
ms.insert(1);
ms.insert(1);
ms.insert(3);
ms.insert(1);
ms.insert(1);
myPrint(ms);
}
int main() {
test();
test2();
system("pause");
return 0;
}
1.7 pair对组创建
功能:
成对出现的数据,可以用队组来承载。
函数原型:
- pair<type, type> p (val1, val2); //创建队组
- pari<type, type> p = make_pair(val1, val2); //创建队组
- p.first // 获取第一个元素
- p.second // 获取第二个元素
示例:
#include <iostream>
#include <string>
using namespace std;
void test() {
pair<string, int> p1("tom", 19);
pair<string, int> p2 = make_pair("echo", 18);
cout << "name: " << p1.first << ",age: " << p1.second << endl;
cout << "name: " << p2.first << ",age: " << p2.second << endl;
}
int main() {
test();
system("pause");
return 0;
}
1.8 set容器排序
问题:
set 容器在插入时会自动给数据排序,且默认是从小到大。那么如果改变排序规则?
方法:
利用防函数,来改变排序规则。
特性:
set存放自定义数据类型,必须指定排序规则;
且指定规则为主键,重复数据只能存入一份。
示例: set存放内置数据类型排序规则从大到小
#include <iostream>
#include <string>
#include<set>
using namespace std;
// set存放内置数据类型排序规则从大到小
class MyCompare {
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
void test01()
{
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
//默认从小到大
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//指定排序规则
set<int,const MyCompare> s2;
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(50);
for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
示例: set存放自定义数据类型排序规则从大到小
#include <iostream>
#include <string>
#include<set>
using namespace std;
class Person {
public:
Person(string name,int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class MyCompare {
public:
bool operator()(const Person& p1, const Person& p2)const {
// 按照年龄降序
// 如果年龄相同,想再跟进姓名排序,这样写
//if (p1.m_age == p2.m_age) {
// return p1.m_name > p2.m_name;
//}
return p1.m_age > p2.m_age;
}
};
void test() {
// 自定义的书记雷,都需要指定排序规则,不然无法插入set
// 本案例按照年龄降序来排序
// 则年龄是主键,会发现年龄18的数据只能插入一条
set<Person,MyCompare> s;
s.insert(Person("tom", 18));
s.insert(Person("echo", 19));
s.insert(Person("lucy", 18));
s.insert(Person("lily", 20));
for (auto item : s) {
cout << "name: " << item.m_name
<< " age: " << item.m_age
<< " " << endl;
}
}
int main() {
test();
system("pause");
return 0;
}