set容器
一、set的基本概念
1.简介:所有元素都会在插入时自动被排序
2.本质:set/multiset属于关联式容器,底层结构是用二叉树实现
3.set和multiset区别
set不允许容器中有重复元素
multiset允许容器中有重复元素
二、set构造和赋值
1.描述:创建set容器以及赋值
2.构造:
- set<T>st; // 默认构造函数
- set(const set &st) //拷贝构造函数
3.赋值:
- set& operator=(const set &st) //重载等号操作符
4.示例
set容器插入数据时用insert
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 test01()
{set<int>s1;s1.insert(10);s1.insert(40);s1.insert(20);s1.insert(30);s1.insert(30);s1.insert(30);//遍历容器//set容器的特点,所有元素被插入的时候会自动排序//set容器不允许插入重复的值printSet(s1);//拷贝构造set<int> s2(s1);printSet(s2);//赋值操作set<int> s3;s3 = s2;printSet(s3);}int main()
{test01();system("pause");return 0;
}
三、set大小和交换
1.描述:set容器的大小、是否为空、交换
2.构造:
- size(); //返回容器中元素的个数
- empty(); //判断容器是否为空
- swap(st); //交换两个集合容器
3.示例:
#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 test01()
{set<int> s1;//插入数据s1.insert(10);s1.insert(30);s1.insert(20); s1.insert(40);printSet(s1);//判断是否为空if (s1.empty()){cout << "s1为空" << endl;}else{cout << "s1不为空" << endl;cout << "s1的元素大小:" << s1.size()<< endl;}
}//交换
void test02()
{set<int> s1;s1.insert(10);s1.insert(30);s1.insert(20);s1.insert(40);set<int> s2;s2.insert(200);s2.insert(100);s2.insert(400);s2.insert(300);cout << "交换前:" << endl;printSet(s1);printSet(s2);cout << "交换后:" << endl;s1.swap(s2);printSet(s1);printSet(s2);}int main()
{//test01();test02();system("pause");return 0;
}
四、set插入和删除
1.描述:set容器进行插入数据和删除数据
2.构造:
- insert(elem); //在容器中插入元素
- clear(); //清除所有元素
- erase(pos); //删除pos迭代器所指向的元素,返回下一个元素的迭代器
- erase(beg,end); //删除区间[beg,end]的所有元素,返回下一个元素的迭代器
- erase(elem); // 删除容器中值为elem的元素
3.示例:
#include<iostream>
using namespace std;
#include<set>
#include<vector>//set容器的插入和删除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(20);s1.insert(10);s1.insert(40);s1.insert(30);//遍历printSet(s1);//删除s1.erase(s1.begin());printSet(s1);//删除重载版本s1.erase(30);printSet(s1);//清空//s1.erase(s1.begin(),s1.end());s1.clear();printSet(s1);} int main()
{test01();system("pause");return 0;
}
五、set容器查找和统计
1.描述:对set容器进行查找数据以及统计数据
2.构造:
- find(key); //查找key是否存在,若存在,返回该元素的迭代器;若不存在,返回set.end()
- count(key); //统计key的元素个数
3.示例:
#include<set>
#include<iostream>
using namespace std;
//set容器查找和统计
void test01()
{//查找set<int>s1;//插入数据s1.insert(30);s1.insert(20);s1.insert(10);s1.insert(40);set<int>::iterator pos = s1.find(40);if (pos != s1.end()) //s1.end()指向最后一个元素的下一个位置{cout << "找到元素:" << *pos << endl;}else{cout << "未找到元素" << endl;}//对于set而言,统计结果不是0就是1//对于multiset而言,统计结果大于1
}//统计
void test02()
{set<int> s1;s1.insert(10);s1.insert(20);s1.insert(30);s1.insert(10);int num = s1.count(100);cout << "统计nus = " << num << endl;
}int main()
{test02();system("pause");return 0;
}
注意: count 对于set而言,统计结果不是0就是1;对于multiset而言,统计结果大于1
六、set和multiset的区别
1.区别:
- set不可以插入重复数据,而multiset可以
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会检测数据,因此可以重复插入
2.示例:
#include<iostream>
#include<set>
using namespace std;//set容器和multiset容器的区别
void test01()
{set <int>s;pair<set<int>::iterator, bool> ret = s.insert(10);if (ret.second){cout << "第一次插入成功" << endl;}else{cout << "第一次插入失败" << endl;}pair<set<int>::iterator,bool> ret2 = s.insert(10);if (ret2.second){cout << "第二次插入成功" << endl;}else{cout << "第二次插入失败" << endl;}multiset<int>s1;//允许插入重复值s1.insert(20);s1.insert(20);for (multiset<int>::iterator it = s1.begin(); it != s1.end(); it++){cout << *it << endl;}cout << endl;
}int main()
{test01();system("pause");return 0;
}
七、pair对组创建
1.功能描述:成对出现的数据,利用对组可以返回两个数组
2.两种创建方式:
- pair<type,type> p(value1,value2)
- pair<type,type> p = make_pair(value1,value2)
3.示例
#include<string>
#include<iostream>
using namespace std;//pair对组的创建
void test01()
{//第一种方式pair<string, int> p("Tom", 20);cout << "姓名:" << p.first << " 年龄:" << p.second << endl;pair<string, int> p2 = make_pair("Jerry", 30);cout << "姓名:" << p2.first << " 年龄:" << p2.second << endl;}int main()
{test01();system("pause");return 0;
}
八、set容器排序
1.学习目标:
- set容器默认排序规则为从小到大,掌握如何改进排序规则
2.主要技术点:
- 利用仿函数,可以改变排序规则
3.示例一:set存放内置数据类型
#include<iostream>
#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(50);s1.insert(30);for (set<int>::iterator it = s1.begin(); it != s1.end(); it++){cout << *it << " ";}cout << endl;//指定排序规则为从大到小set<int, MyCompare>s2;s2.insert(10);s2.insert(40);s2.insert(20);s2.insert(50);s2.insert(30);for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++){cout << *it << " ";}cout << endl;
}int main()
{test01();system("pause");return 0;
}
注意仿函数中,operator()重载“()”时需要加const
class MyCompare
{
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
没加const报错的原因:通过在 operator()
函数后加上 const
修饰符,你告诉编译器这个函数不会修改对象的状态,因此可以在 const
对象上调用。这样应该能够解决与 C3848
错误相关的问题。
总结:利用仿函数指定set容器的排序规则
4.示例二:set存放自定义数据类型
#include<iostream>
#include<set>
#include<string>
using namespace std;//set容器排序,存放自定义数据类型
class Person
{
public:Person(string name,int age){this->m_Name = name;this->m_Age = age;}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 test01()
{//自定义的数据类型 都会指定排序规则set<Person,comparePerson> s1;//创建Person对象Person p1("刘备", 24);Person p2("张飞", 14);Person p3("关羽", 50);Person p4("Jerry", 28);Person p5("Tom", 39);s1.insert(p1);s1.insert(p2);s1.insert(p3);s1.insert(p4);s1.insert(p5);for (set<Person, comparePerson>::iterator it = s1.begin(); it != s1.end(); it++){cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;}
}int main()
{test01();system("pause");return 0;
}
map容器
一、map的基本概念
1.简介:
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
2.本质:
- map/multimap属于关联式容器,底层结构是二叉树
3.优点:
- 可以根据key值快速查找到value值
4.map/multimap区别
- map不允许容器中有重复key值元素
- multimap允许容器有重复key值元素
二、map构造和赋值
1.功能描述:对map容器进行构造和赋值操作
2.函数原型:
构造:
- map<T1,T2> mp; //map默认构造
- map(const map &mp); //拷贝构造函数
赋值:
- mp& operator = (const map &mp) //重载等号运算符
3.示例:
#include<iostream>
#include<map>
using namespace std;//map容器 构造和赋值
void printMap(map<int, int>& m)
{for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "key = " << (*it).first << " value = " << it->second << endl;}cout << endl;
}void test01()
{//创建map容器map<int, int> m;m.insert(pair<int, int>(1, 10));m.insert(pair<int, int>(2, 30));m.insert(pair<int, int>(3, 30));printMap(m);//拷贝构造map<int, int>m2(m);printMap(m2);//赋值map<int, int>m3;m3 = m2;printMap(m3);
}int main()
{test01();system("pause");return 0;
}
总结:map中所以元素是成对出现,插入数据时要使用对组
二、map容器大小和交换
1.功能描述:统计map容器大小以及交换map容器
2.函数原型
- size(); //返回容器中元素的数目
- empty(); //判断容器是否为空
- swap(); //交换两个集合
3.示例:
#include<iostream>
#include<map>
using namespace std;//map容器 大小和交换void printMap(map<int, int>& m)
{for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "k = " << it->first << " value" << it->second << endl;}cout << endl;
}void test01()
{//大小map<int, int> m;m.insert(pair<int, int>(1, 10));m.insert(pair<int, int>(4, 30));m.insert(pair<int, int>(3, 20));if (m.empty()){cout << "m为空" << endl;}else{cout << "m不为空" << endl;cout << "m大小:" << m.size() << endl;cout << "m内容:" << endl;printMap(m);}
}void test02()
{map<int, int> m;//for (int i = 1; i < 4; i++)//{// m.insert(pair<int, int>(i, i*10));//}//printMap(m);m.insert(pair<int, int>(1, 10));m.insert(pair<int, int>(3, 30));m.insert(pair<int, int>(2, 20));map<int, int>m2;m2.insert(pair<int, int>(4, 40));m2.insert(pair<int, int>(6, 60));m2.insert(pair<int, int>(3, 80));cout << "交换前:" << endl;cout << "m:" << endl;printMap(m);cout << "m2:" << endl;printMap(m2);cout << "-------------------------------" << endl;swap(m, m2);cout << "交换后:" << endl;cout << "m:" << endl;printMap(m);cout << "m2:" << endl;printMap(m2);}int main()
{//test01();test02();system("pause");return 0;
}
三、map容器插入和删除
1.功能描述:map容器进行插入数据和删除数据‘
2.函数原型:
- insert(elem); //在容器中插入元素
- clear(); // 清除所以元素
- erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
- erase(beg,end); //删除(beg,end)区间的元素,返回下一个元素的迭代器
- erase(key); //删除key值和其元素
3.示例:
#include<iostream>
#include<map>
using namespace std;void printMap(map<int, int>& m)
{for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "key = " << it->first << " value = " << it->second << endl;}cout << endl;
}void test01()
{map<int, int>m;//插入//第一种m.insert(pair<int, int>(1, 10));//第二种m.insert(make_pair(2, 20));//第三种m.insert(map<int, int>::value_type(0, 10));//第四种m[4] = 40;//cout << m[5] << endl;//没有的时候默认插入0printMap(m);//删除m.erase(m.begin());printMap(m);m.erase(2);//按照key删除printMap(m);m.erase(m.begin(),m.end());//清空printMap(m);m.insert(pair<int,int>(0, 33));m.clear();//也是清空printMap(m);
}int main()
{test01();system("pause");return 0;
}
四、map容器查找和统计
1.对map容器进行查找数据以及统计数据
2.函数原型
- find(key); //查找key是否存在,返回该键的元素的迭代器;若不存在,返回set.end()
- count(key); //统计key出现个数
3.示例:
#include<iostream>
#include<map>
using namespace std;void test01()
{//查找map<int, int>m;m.insert(pair<int, int>(1, 10));m.insert(pair<int, int>(3, 30));m.insert(pair<int, int>(2, 20));map<int, int>::iterator pos = m.find(3);//find返回迭代器if (pos != m.end()){cout << "找到元素key = " << (*pos).first << " value" << pos->second << endl;}else{cout << "未找到元素" << endl;}//统计 // map不允许插入重复key 对于count统计结果要么0,要么1//multimap允许插入重复key 对于count统计结果可以大于1int num = m.count(3);cout << "num = " << num << endl;multimap<int, int> m2;m2.insert(pair<int, int>(1, 10)); m2.insert(pair<int, int>(1, 10));m2.insert(pair<int, int>(1, 10));int num2 = m2.count(1);cout << "num2 = " << num2 << endl;}int main()
{test01();system("pause");return 0;
}
五、map容器排序
1.学习目标:map容器默认排序规则为 按照key值进行从小到大排序,学习如何改变排序规则
2.技术要点:
- 利用仿函数,可以改变排序规则
3.示例一:内置数据类型排序
#include<iostream>
#include<map>
using namespace std;class myCompare
{
public:bool operator()(int v1, int v2) const{//降序return v1 > v2;}
};void test01()
{map<int, int>m;m.insert(make_pair(1, 10));m.insert(make_pair(2, 20));m.insert(make_pair(5, 50));m.insert(make_pair(3, 30));m.insert(make_pair(4, 40));cout << "默认从小到大排序:" << endl;for (map<int, int>::iterator it = m.begin(); it != m.end(); it++){cout << "key = " << it->first << " value" << it->second << endl;}cout << endl;map<int, int, myCompare>m2;m2.insert(make_pair(1, 10));m2.insert(make_pair(2, 20));m2.insert(make_pair(5, 50));m2.insert(make_pair(3, 30));m2.insert(make_pair(4, 40));cout << "改变从大到小排序:" << endl;for (map<int, int, myCompare>::iterator it = m2.begin(); it != m2.end(); it++){cout << "key = " << it->first << " value" << it->second << endl;}cout << endl;}int main()
{test01();system("pause");return 0;}
3.示例二:自定义数据类型排序
#include<iostream>
#include<map>
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()(int v1, int v2) const{return v1 > v2;}
};void test01()
{map<int, Person> f;Person p1("刘备", 24);Person p2("小阿备", 2); Person p3("关羽", 20);Person p4("小阿飞", 3);f.insert(make_pair(1, p1));f.insert(make_pair(4, p4));f.insert(make_pair(3, p3));f.insert(make_pair(2, p2));cout << "----------默认排序----------" << endl;for (map<int, Person>::iterator it = f.begin(); it != f.end(); it++){cout << "key = " << it->first << " 姓名:" << it->second.m_Name << " 年龄:" << it->second.m_Age << endl;}cout << endl;cout << "----------从大到小排序----------" << endl;map<int, Person, myCompare> f2; //只能按照key值排序Person p11("刘备", 24);Person p12("小阿备", 2);Person p13("关羽", 20);Person p14("小阿飞", 3);f2.insert(make_pair(1, p11));f2.insert(make_pair(4, p14));f2.insert(make_pair(3, p13));f2.insert(make_pair(2, p12));for (map<int, Person, myCompare>::iterator it = f2.begin(); it != f2.end(); it++){cout << "key = " << it->first << " 姓名:" << it->second.m_Name << " 年龄:" << it->second.m_Age << endl;}cout << endl;
}int main()
{test01();system("pause");return 0;}
总结:自定义数据类型也只能按照key值排序,不能按照Person的年龄排序。