set/multiset容器的简单认识
-
- set基本概念
-
- [set与multiset 的区别:](#set与multiset 的区别:)
- set容器的构造和赋值
- set容器的大小和交换
- set容器的插入与删除
- set容器的查找和统计
- set容器-set和multiset的区别
- set容器内置类型指定排序规则
- set容器自定义数据类型指定排序规则
- pair对组创建
- map容器的基本概念
set基本概念
set的所有元素在插入时会自动被排序,其本质 set/multiset 属于并联式容器,底层结构是用二叉树
实现的
set与multiset 的区别:
- set不允许容器中有重复的元素
- multiset允许容器中有重复的元素
使用时仅需要包含一个 set
的头文件
cpp
#include <set>
set容器的构造和赋值
set<T> st;
默认构造函数
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
//默认构造函数
set<int> st;
st.insert(12);
}
set(const set<T>& st);
拷贝构造函数
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
//默认构造函数
set<int> st;
st.insert(12);
//拷贝构造函数
set<int> st2(st);
}
set& operator=(const set<T>& st);
重载等号操作符
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
//默认构造函数
set<int> st;
st.insert(12);
set<int> st2;
//重载等号操作符赋值
st2 = st;
}
set容器的大小和交换
用于统计set容器的大小以及交换set容器
size();
返回容器中元素的数目
cpp
在这里插入代码片
empty();
判断容器是否为空
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
string str = (((int)st.empty()) == 0) ? "不为空" : "为空";
std::cout << "容器st是否为空: " << str << std::endl;
}
swap(st);
交换两个集合容器
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
set<int> st2;
for (int i = 11; i < 20; i++)
{
st2.insert(i);
}
std::cout << "执行交换前 st的数据信息为:" << std::endl;
printf(st);
std::cout << "执行交换前 st2的数据信息为:" << std::endl;
printf(st2);
st.swap(st2);
std::cout << "执行交换后 st的数据信息为:" << std::endl;
printf(st);
std::cout << "执行交换后 st2的数据信息为:" << std::endl;
printf(st2);
}
set容器的插入与删除
insert(elem);
在容器中插入元素
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
for (int i =100; i > 90; i--)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
}
以上案例说明set容器在插入元素后,会进行排序
clear();
清除所有元素
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
st.clear();
std::cout << "清空数据据后 st的数据信息为:" << std::endl;
printf(st);
}
erase(pos);
删除pos迭代器所指的元素,返回下一个元素速度迭代器
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
set<int>::iterator it = st.erase(st.begin());
std::cout << "删除st.begin元素后 返回的下一元素位置指向:" << *it << std::endl;
std::cout << "删除st.begin元素后 set容器值列表为:" << std::endl;
printf(st);
}
erase(beg, end);
删除区间[beg, end)的所有元素,返回下一个元素的迭代器
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
set<int>::iterator it = st.erase(st.begin(), ++(++st.begin()));
std::cout << "删除[st.begin, ++(++st.begin()))元素后 返回的下一元素位置指向:" << *it << std::endl;
std::cout << "删除元素后 set容器值列表为:" << std::endl;
printf(st);
}
earse(elem);
删除容器中值为elem的元素
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
st.erase(1);
std::cout << "删除元素 1 后 set容器值列表为:" << std::endl;
printf(st);
}
set容器的查找和统计
find(key);
查找key是否存在,若存在,返回该key值的元素的迭代器,若不存在,返回set.end();
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const set<int> st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
set<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
set<int>::iterator it = st.find(1);
std::cout << "查找元素 1 的位置:" << &it << " 其指向的元素值为:" << *it << std::endl;
set<int>::iterator it_not_find = st.find(100);
if (it_not_find == st.end())
{
std::cout << "元素100 未查找到" << std::endl;
}
}
count(key);
统计元素key的个数
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
void printf(const multiset<int> st)
{
for (multiset<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main()
{
multiset<int> st;
for (int i = 0; i < 10; i++)
{
st.insert(i);
st.insert(i);
st.insert(i);
}
std::cout << "插入数据后 st的数据信息为:" << std::endl;
printf(st);
int count = st.count(1);
std::cout << "统计元素 1 的数量,元素共有:" << count << " 个:" << std::endl;
}
这里使用multiset举例,因为set不会存储重复插入的元素,所有元素数量均为1个
set容器-set和multiset的区别
- set不可以插入重复数据,而multiset可以插入重复数据
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会监测数据,因此可以插入重复数据
cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;
int main()
{
set<int> st;
pair<set<int>::iterator, bool> ret = st.insert(3);
if (ret.second)
{
std::cout << "插入成功" << std::endl;
}
else
{
std::cout << "插入失败" << std::endl;
}
ret = st.insert(3);
if (ret.second)
{
std::cout << "插入成功" << std::endl;
}
else
{
std::cout << "插入失败" << std::endl;
}
}
内部使用的 pair<set<int>::iterator, bool>
是一个键值对的结构,调用set.insert() 后,会触发重复值监测,如果检测到重复值,那么会导致返回插入失败的结果
multiset没有这个操作
set容器内置类型指定排序规则
set容器默认排序规则是从小到大,利用仿函数,可以改变排序规则
cpp
#include <iostream>
#include <string>
#include <set>
#include <ctime>
using namespace std;
class CustomCompare
{
public:
//数据可能被修改,所以需要使用const限定调用函数的set对象不被修改
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
void printf(const set<int>& st)
{
for (set<int>::const_iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
void printf_custom(set<int, CustomCompare>& st)
{
for (set<int, CustomCompare>::iterator it = st.begin(); it != st.end(); it++)
{
std::cout << *it << " ";
}
std::cout << std::endl;
}
void init(set<int>& st)
{
//随机数种子
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++)
{
st.insert(rand() % 60 + 40);
}
}
int main()
{
set<int> st;
init(st);
std::cout << "初始化set后的值(当前是默认升序排列):" << std::endl;
printf(st);
//指定排序规则为从大到小 - 需要在创建容器的时候指定
set<int, CustomCompare> st2;
st2.insert(12);
st2.insert(14);
st2.insert(54);
st2.insert(34);
st2.insert(76);
std::cout << "初始化set后的值(当前是定义了自定义仿函数排序规则):" << std::endl;
printf_custom(st2);
}
set容器自定义数据类型指定排序规则
cpp
#include <iostream>
#include <string>
#include <set>
#include <ctime>
using namespace std;
class Person
{
private:
string m_Name;
int m_Age;
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
void printf() const
{
std::cout << "姓名:" << this->m_Name << " 年龄:" << this->m_Age << std::endl;
}
int getAge()
{
return this->m_Age;
}
};
class PersonCompare
{
public:
bool operator()(Person p1, Person p2) const
{
return p1.getAge() > p2.getAge();
}
};
void printf(const set<Person, PersonCompare>& st)
{
for (set<Person, PersonCompare>::const_iterator it = st.begin(); it != st.end(); it++)
{
it->printf();
}
}
int main()
{
set<Person, PersonCompare> st;
Person p1("张三",12);
Person p2("李四", 54);
Person p3("王二", 23);
Person p4("麻子", 87);
Person p5("刘武", 45);
Person p6("无硫", 22);
st.insert(p1);
st.insert(p2);
st.insert(p3);
st.insert(p4);
st.insert(p5);
st.insert(p6);
printf(st);
}
pair对组创建
成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair<type, type> p (value, value2);
pair<type, type> p = make_pair(value, value2);
cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
pair<string, int> p1("测试Pair", 111);
std::cout << "插入的值为:(" << p1.first << ", " << p1.second << ")" << std::endl;
p1 = make_pair("测试pair第二次", 121);
std::cout << "插入的值为:(" << p1.first << ", " << p1.second << ")" << std::endl;
}
map容器的基本概念
- map中所有元素都是pair
- pair中的第一个元素是key(键值),起到索引所用,第二个元素是value(实值)
- 所有元素都会根据元素的键值自动排列
本质:
- map/multimap 属于并联式容器,底层结构是用二叉树实现
优点:
- 可以根据key值快速查找到value值
map和multimap 的区别:
- map不允许容器中有重复的key值元素
- multimap允许容器中有重复的key值元素
map容器构造和赋值
map<T1, T2> mp;
默认构造函数
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
//默认构造函数
map<string, int> mp;
}
map(const map<T1, T2>& mp);
拷贝构造函数
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
//默认构造函数
map<string, int> mp;
//拷贝构造
map<string, int> mp2(mp);
}
map& operator=(const map& map);
重载等号操作符
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
//默认构造函数
map<string, int> mp;
//重载=号赋值
map<string, int> mp2 = mp;
}
map容器大小和交换
size();
返回容器中的元素的数目
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mp;
std::cout << mp.size() << std::endl;
}
empty();
判别容器中元素是否为空
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mp;
mp.insert(pair<string,int>("测试", 12));
std::cout << mp.empty() << std::endl;
}
swap(st);
交换两个集合容器
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mp;
map<string, int> mp2;
mp.swap(mp2);
}
map容器插入和删除
insert(elem);
在容器中插入元素
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, int> mp;
//第一种方法
mp.insert(pair<string,int>("测试", 12));
//第二种方法
mp.insert(make_pair("测试2", 12));
//第三种方法
mp.insert(map<int, int>::value_type("测试3", 12))
//第四种 不建议使用 没有这个key值调用时,会根据您的key值创建一个信息数据出来并填充默认值
mp["测试5"] = 13;
for(map<string, int>::iterator it = mp.begin(); it != mp.end(); it++)
{
std::cout << "(" << (*it).first << " ," << (*it).second << ")" << std::endl;
}
}
clear();
清除所有元素
cpp
map<string, int> mp;
mp.insert(pair<string,int>("测试", 12));
mp.clear();
erase(pos);
删除pos迭代器所指的元素,返回下一个元素的迭代器
cpp
map<string, int> mp;
mp.insert(pair<string,int>("测试", 12));
map<string, int>::iterator next = mp.erase(mp.begin());
erase(beg, end);
删除[beg, end)区间所有的元素,返回下一个元素的迭代器
cpp
map<string, int> mp;
mp.insert(pair<string,int>("测试", 12));
map<string, int>::iterator next = mp.erase(mp.begin(), mp.end());
erase(key);
删除容器中key值为key的元素
cpp
map<string, int> mp;
mp.insert(pair<string,int>("测试", 12));
mp.erase(12);
map容器查找和统计
find(key);
查找key是否存在,若存在,返回该键的元素的迭代器,若不存在,返回map.end();
cpp
map<string, int> mp;
mp.insert(pair<string, int>("测试", 12));
map<string, int>::iterator find_result = mp.find("测试");
if (find_result == mp.end())
{
std::cout << "未查找" << std::endl;
}
else
{
std::cout << "查找到结果" << std::endl;
}
count(key);
统计key元素个数
cpp
multimap <string, int> mp;
mp.insert(pair<string, int>("测试", 12));
mp.insert(pair<string, int>("测试", 13));
int count = mp.count("测试");
std::cout << "查找到结果" << count << "个" << std::endl;
map容器排序
利用仿函数,改变排序规则
cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Compare
{
public:
bool operator()(string k1, string k2) const
{
return k1 > k2;
}
};
int main()
{
multimap <string, int , Compare> mp;
mp.insert(pair<string, int>("测试1", 12));
mp.insert(pair<string, int>("测试2", 13));
for (map<string, int>::iterator it = mp.begin(); it != mp.end(); it++)
{
std::cout << "(" << (*it).first << ", " << (*it).second << ")" << std::endl;
}
}