目录
set容器
set的默认构造
set的插入与迭代器
set集合的元素排序
set集合的初始化及遍历
从小到大(默认情况下)
从大到小
仿函数
set的查找
pair的使用
multiset容器
map和multimap容器
map的插入与迭代器
map的大小
map的删除
map的查找
关联式容器(Associated containers),元素位置取决于特定的排序准则,和插入顺序无关
在c++STL中主要有set、multiset、map、multimap
set容器
- set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
- set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。
- set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
set的默认构造
set<int> setInt; //一个存放int的set容器。
set<float> setFloat; //一个存放float的set容器。
set<string> setString; //一个存放string的set容器。
multiset<int> mulsetInt; //一个存放int的multi set容器。
multi set<float> multisetFloat; //一个存放float的multi set容器。
multi set<string> multisetString; //一个存放string的multi set容器。
set的插入与迭代器
- set.insert(elem); //在容器中插入元素。
- set.begin(); //返回容器中第一个数据的迭代器。
- set.end(); //返回容器中最后一个数据之后的迭代器。
- set.rbegin(); //返回容器中倒数第一个元素的迭代器。
- set.rend(); //返回容器中倒数最后一个元素的后面的迭代器。
set集合的元素排序
- set<int,less<int> > setIntA; //该容器是按升序方式排列元素。
- set<int,greater<int>> setIntB; //该容器是按降序方式排列元素。
- set<int> 相当于 set<int,less<int>>。
- less<int>与greater<int>中的int可以改成其它类型,该类型主要要跟set容纳的数据类型一致。
set集合的初始化及遍历
从小到大(默认情况下)
//集合 元素唯一 自动排序 不能按照[]方式插入元素
//默认情况下是从小到大
void main91()
{
set<int> set1;
for (int i = 0; i < 5; i++)
{
int tmp = rand();
set1.insert(tmp);
}
set1.insert(100);
set1.insert(100);
set1.insert(100);
for (set<int>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
while (!set1.empty())
{
set<int>::iterator it = set1.begin();
cout << *it << " ";
set1.erase(set1.begin());
}
}
从大到小
void main92()
{
set<int,greater<int>> set1;
for (int i = 0; i < 5; i++)
{
int tmp = rand();
set1.insert(tmp);
}
set1.insert(100);
set1.insert(100);
set1.insert(100);
for (set<int,greater<int>>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
仿函数
对于复杂的数据类型set集合是通过用户自定义来排序的,主要利用的就是仿函数这个机制。
//仿函数
struct FuncStudent
{
bool operator()(const Student& left, const Student& right) const
{
if (left.m_age < right.m_age)
{
return true;
}
else
{
return false;
}
}
};
void main93()
{
set<Student, FuncStudent> set1;
Student s1("s1", 32);
Student s2("s2", 22);
Student s3("s3", 16);
Student s4("s4", 55);
Student s5("s5", 32);
set1.insert(s1);
set1.insert(s2);
set1.insert(s3);
set1.insert(s4);
set1.insert(s5);//两个一样的值
//如何知道插入的结果
//遍历
for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << it->m_age << "\t" << it->m_name << endl;
}
}
set的查找
- set.find(elem); //查找elem元素,返回指向elem元素的迭代器。
- set.count(elem); //返回容器中值为elem的元素个数。对set来说,要么是0,要么是1。对multiset来说,值可能大于1。
- set.lower_bound(elem); //返回第一个>=elem元素的迭代器。
- set.upper_bound(elem); // 返回第一个>elem元素的迭代器。
- set.equal_range(elem); //返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。
pair的使用
- pair译为对组,可以将两个值视为一个单元。
- pair<T1,T2>存放的两个值的类型,可以不一样,如T1为int,T2为float。T1,T2也可以是自定义类型。
- pair.first是pair里面的第一个值,是T1类型。
- pair.second是pair里面的第二个值,是T2类型。
set<int> setInt;
... //往setInt容器插入元素1,3,5,7,9
pair< set<int>::iterator , set<int>::iterator > pairIt = setInt.equal_range(5);
set<int>::iterator itBeg = pairIt.first;
set<int>::iterator itEnd = pairIt.second;
//此时 *itBeg==5 而 *itEnd == 7
//如何判断insert的返回值
void main94()
{
set<Student, FuncStudent> set1;
Student s1("s1", 32);
Student s2("s2", 22);
Student s3("s3", 16);
Student s4("s4", 55);
Student s5("s5", 32);
pair<set<Student, FuncStudent>::iterator, bool> pair1;
pair1 = set1.insert(s1);
if (pair1.second)
{
cout << "插入s1成功" << endl;
}
else
{
cout << "插入s1失败" << endl;
}
set1.insert(s2);
set1.insert(s3);
set1.insert(s4);
pair1 = set1.insert(s5);//两个一样的值
if (pair1.second)
{
cout << "插入s5成功" << endl;
}
else
{
cout << "插入s5失败" << endl;
}
//遍历
for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << it->m_age << "\t" << it->m_name << endl;
}
}
multiset容器
- multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
- 不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
void main101()
{
multiset<int> set1;
int tmp;
cout << "请输入multiset集合的值:";
scanf("%d", &tmp);
while (tmp != 0)
{
set1.insert(tmp);
cout << "请输入multiset集合的值:";
scanf("%d", &tmp);
}
//遍历
for (multiset<int>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << *it << " ";
}
cout << endl;
while (!set1.empty())
{
multiset<int>::iterator it = set1.begin();
cout << *it << " ";
set1.erase(set1.begin());
}
}
map和multimap容器
- map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。
- map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
- map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。
- map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。
- multimap与map的区别:map支持唯一键值,每个键只能出现一次;而multimap中相同键可以出现多次。multimap不支持[]操作符。
map的插入与迭代器
- map.insert(...); //往容器插入元素,返回pair<iterator,bool>
- 在map中插入元素的三种方式:
假设 map<int, string> mapStu;
- 一、通过pair的方式插入对象
mapStu.insert( pair<int,string>(3,"小张") );
- 二、通过pair的方式插入对象
mapStu.inset(make_pair(-1, “校长-1”));
- 三、通过value_type的方式插入对象
mapStu.insert( map<int,string>::value_type(1,"小李") );
- 四、通过数组的方式插入值
mapStu[3] = “小刘";
mapStu[5] = “小王";
- 前三种方法,采用的是insert()方法,该方法返回值为pair<iterator,bool>
- 第四种方法非常直观,但存在一个性能的问题。插入3时,先在mapStu中查找主键为3的项,若没发现,则将一个键为3,值为初始化值的对组插入到mapStu中,然后再将值修改成“小刘”。若发现已存在3这个键,则修改这个键对应的value。
- string strName = mapStu[2]; //取操作或插入操作
- 只有当mapStu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。
map的大小
- map.size(); //返回容器中元素的数目
- map.empty();//判断容器是否为空
map的删除
- map.clear(); //删除所有元素
- map.erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
- map.erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
- map.erase(keyElem); //删除容器中key为keyElem的对组。
map的查找
- map.find(key); 查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
- map.count(keyElem); //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
//map的添加/遍历/删除
void main111()
{
map<int, string> map1;
//方法一
map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(pair<int, string>(2, "teacher02"));
//方法二
map1.insert(make_pair(3, "teacher03"));
map1.insert(make_pair(4, "teacher04"));
//方法三
map1.insert(map<int, string>::value_type(5, "teacher05"));
map1.insert(map<int, string>::value_type(6, "teacher06"));
//方法四
map1[7] = "teacher07";
map1[8] = "teacher08";
//容器的遍历
for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
{
cout << it->first << "\t" << it->second << endl;
}
cout << "遍历结束" << endl;
//容器的删除
while (!map1.empty())
{
map<int, string>::iterator it = map1.begin();
cout << it->first << "\t" << it->second << endl;
map1.erase(it);
}
}
//插入的四种方法异同
//前三种返回值是pair<iterator,bool>
//前三种方法若key已经存在则报错
//方法四 若key已经存在则覆盖
void main112()
{
map<int, string> map1;
//方法一
pair<map<int, string>::iterator,bool> mypair1 = map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(pair<int, string>(2, "teacher02"));
//方法二
pair<map<int, string>::iterator, bool> mypair3 = map1.insert(make_pair(3, "teacher03"));
map1.insert(make_pair(4, "teacher04"));
//方法三
pair<map<int, string>::iterator, bool> mypair5 = map1.insert(map<int, string>::value_type(5, "teacher05"));
if (mypair5.second)
{
cout << mypair5.first->first << mypair5.first->second << endl;
}
else
{
cout << "key5 插入失败" << endl;
}
pair<map<int, string>::iterator, bool> mypair6 = map1.insert(map<int, string>::value_type(5, "teacher06"));
if (mypair6.second)
{
cout << mypair6.first->first << mypair6.first->second << endl;
}
else
{
cout << "key5 插入失败" << endl;
}
//方法四
map1[7] = "teacher07";
map1[7] = "teacher77";
//容器的遍历
for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
{
cout << it->first << "\t" << it->second << endl;
}
cout << "遍历结束" << endl;
}
void main113()
{
map<int, string> map1;
//方法一
map1.insert(pair<int, string>(1, "teacher01"));
map1.insert(pair<int, string>(2, "teacher02"));
//方法二
map1.insert(make_pair(3, "teacher03"));
map1.insert(make_pair(4, "teacher04"));
//方法三
map1.insert(map<int, string>::value_type(5, "teacher05"));
map1.insert(map<int, string>::value_type(6, "teacher06"));
//方法四
map1[7] = "teacher07";
map1[8] = "teacher08";
//容器的遍历
for (map<int, string>::iterator it = map1.begin(); it != map1.end(); it++)
{
cout << it->first << "\t" << it->second << endl;
}
cout << "遍历结束" << endl;
//map的查找
map<int, string>::iterator it2 = map1.find(100);
if (it2 == map1.end())
{
cout << "key 100的值不存在" << endl;
}
else
{
cout << it2->first << "\t" << it2->second << endl;
}
//equal_range
pair<map<int, string>::iterator, map<int, string>::iterator> mypair = map1.equal_range(5);//返回两个迭代器 形成一个pair
//第一个迭代器>=5的位置
//第二个迭代器>5的位置
if (mypair.first == map1.end())
{
cout << "第一个迭代器不存在" << endl;
}
else
{
cout << mypair.first->first << "\t" << mypair.first->second << endl;
}
//使用第二个迭代器
if (mypair.second == map1.end())
{
cout << "第一个迭代器不存在" << endl;
}
else
{
cout << mypair.second->first << "\t" << mypair.second->second << endl;
}
}