文章目录
pair对组
创建
//第一种方法:构造函数
pair<string,int> p ("Tom",10);
cout<<"姓名:"<<p.first<<" "<<"年龄:"<<p.second<<endl;
//第二种方法:make_pair函数
pair<string,int>p = make_pair("jerry",18);
cout<<"姓名:"<<p.first<<" "<<"年龄:"<<p.second<<endl;
关联式容器(set)
set的特性是:所有元素都会根据元素的键值自动被排序。set和map不同,map可以同时拥有实值和键值,而set只能拥有键值,set的元素既是键值又是实值。set不允许两个相同元素有相同的键值。
不能通过set的迭代器改变set的元素,因为set的元素值就是其键值,而键值有关系到set元素的排序,如果随意改变set中的元素值,那么就会打乱排好的顺序,会严重破坏set组织。换句话说:set的iterator是一种cosnt_iterator。
set拥有和list某些相同的性质,当对容器中的元素进行插入或者删除的时候,其他位置元素的迭代器不会受影响。
multiset特性和用法和set相同,唯一的差别在于它允许键值重复。其两者的底层实现是红黑树(这也是为什么不能通过迭代器来修改元素值的原因,会导致平衡二叉搜索树的顺序被打乱)。
插入和删除
insert(elem);//在容器中插入元素 没有push_back,直接讲元素插入即可
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素
erase(beg,end);//删除区间[beg,end)的所有元素
erase(elem);//删除容器中值为elem的元素,类似remove()用法
大小操作
size()//返回容器中元素的个数
empty()//判断容器是否为空
赋值操作
set& operator=(const set &lst)//重载等号=运算符
swap(lst)//交换两个集合容器
独有:查找操作
find(key)//查找键key是否存在。若存在,返回该键的元素迭代器;若不存在,返回set.end();
//string容器中也有find函数,其中返回的是首字符的数组下标,是int类型的,这里set容器中的find函数返回的是迭代器。
count(key)//查找键key元素的个数,注意在set中非0即1.返回值是int类型数据
lower_bound(keyElem)//返回第一个key>=keyElem元素的迭代器
upper_bound(keyElem)//返回第一个key>keyElem元素的迭代器
equal_range(keyElem)//返回容器中key与keyELem相等的上下限的两个迭代器
//find用法:
int main()
{
set<int> s;
s.insert(10);
s.insert(20);
s.insert(40);
s.insert(30);
set<int>::iterator pos = s.find(30);
if (pos != s.end())
{
cout << "找到了元素:" << *pos << endl;
}
else
{
cout << "没有找到" << endl;
}
return 0;
}
//equal_range的用法:
int main()
{
set<int> s;
s.insert(10);
s.insert(20);
s.insert(40);
s.insert(30);
pair<set<int>::iterator, set<int>::iterator> ret = s.equal_range(30);
if (ret.first != s.end())
{
cout << "equal_range中的lower_bound的值为:" << *ret.first << endl;
}
else
{
cout << "未找到" << endl;
}
if (ret.second != s.end())
{
cout << "equal_range中的upper_bound的值为:" << *ret.second << endl;
}
else
{
cout << "未找到" << endl;
}
}
set不允许插入相同的值,multiset允许插入相同的值
//set容器的insert函数的返回值是pair<iterator,bool>类型的队组。
//multiset容器的insert函数的返回值是iterator迭代器。
//检查两次插入元素10是否成功
int main()
{
set<int>s;
pair<set<int>::iterator, bool> ret = s.insert(10);
if (ret.second)
{
cout << "成功" << endl;
}
else
{
cout << "失败" << endl;
}
ret = s.insert(10);
if (ret.second)
{
cout << "成功" << endl;
}
else
{
cout << "失败" << endl;
}
return 0;
}
//最终的结果是:成功 失败,所以说只有第一次插入成功。
从大到小排列
set容器中的元素是按照从小到大的顺序排列的,set容器的迭代器是只读的,也就是说只要插入,那么整个容器就已经是确定好的,无法对其中元素进行修改。那怎么讲元素按照从大到小来排列呢?
//set<int, >s; 如果想要得到从大到小排列的set容器,那么在插入元素之前就应该将set设计好。在< >中加入仿函数。这里是不能加入回调函数的,因为在<>中的int是数据类型,所以应该在<>中加入的应该还是数据类型,那么就用仿函数。仿函数就是一个类。
class myCompareInt
{
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
};
int main()
{
set<int, myCompareInt> s;
s.insert(10);
s.insert(30);
s.insert(20);
s.insert(40);
for (set<int, myCompareInt>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << endl;
}
return 0;
}
对于自定义的数据类型
例如自定义类型person,有两个属性(年龄和姓名),但是set不知道如何进行排列,所以如果直接将person类型的数据存入set容器中是会报错的。所以可以考虑使用仿函数来进行排序规则的规定(仿函数:写一个类,重载()来进行比较两个person对象)。
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//这个const还是需要的
{
//按照年龄的升序
return p1.m_age < p2.m_age;
}
};
int main()
{
set<Person,myCompare>s;
Person p1("aa", 10);
Person p2("bb", 20);
Person p3("cc", 30);
Person p4("dd", 40);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person,myCompare>::iterator it = s.begin(); it != s.end(); it++)
{
cout << (*it).m_name <<" "<<(*it).m_age << endl;
}
return 0;
}
关联式容器(map)
map的特性:所有元素都会根据元素的键值自动排序。map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值(通过key可以访问到value)。map不允许两个元素有相同的键值。
不可以通过map的迭代器改变map的键值,因为map的键值关系到map元素的排列规则。任意改变map键值将会严重破坏map组织;如果想修改元素的实值是可以的。map和list拥有某些相同的特性,当对容器中的元素进行新增操作和删除操作的时候,其他的迭代器不会受到影响。
Multimap和map的操作相同,唯一的区别是multimap键值可以重复。他俩都是以红黑树为底层实现机制。
插入和删除
insert(elem);//在容器中插入元素 没有push_back,直接讲元素插入即可。
//1,m.insert(pair<int,int>(1,1));匿名对组
//2,m.insert(make_pair(2,20));
//3,m.insert(map<int,int>::value_type(3,30)); 不推荐。
//4,m[4]=40; 不推荐,因为只要写出m[5],就会将这个元素创建出来。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素
erase(beg,end);//删除区间[beg,end)的所有元素
erase(keyElem);//删除容器中key为keyElem的队组,set中是删除对应elem值的元素。类似remove()用法
大小操作
size()//返回容器中元素的个数
empty()//判断容器是否为空
赋值操作
map& operator=(const map &lst)//重载等号=运算符
swap(mp)//交换两个集合容器
独有:查找操作
find(key)//查找键key是否存在。若存在,返回该键的元素迭代器;若不存在,返回map.end();
//string容器中也有find函数,其中返回的是首字符的数组下标,是int类型的,这里set容器中的find函数返回的是迭代器。
count(keyElem)//查找键key为keyElem的队组的个数,对map来说非0即1.返回值是int类型数据,对multimap来说,值可能大于1.
lower_bound(keyElem)//返回第一个key>=keyElem元素的迭代器
upper_bound(keyElem)//返回第一个key>keyElem元素的迭代器
equal_range(keyElem)//返回容器中key与keyELem相等的上下限的两个迭代器
//find用法:
int main()
{
map<int, int> s;
s.insert(pair<int, int>(1, 10));
s.insert(pair<int, int>(2, 20));
s.insert(pair<int, int>(3, 30));
s.insert(pair<int, int>(4, 40));
map<int, int>::iterator pos = s.find(2);
if (pos != s.end())
{
cout << "找到了元素:" << pos->first<<" "<<pos->second << endl;
}
else
{
cout << "没有找到" << endl;
}
return 0;
}
//equal_range(keyElem)用法:
pair<map<int, int>::iterator, map<int, int>::iterator> ret2 = m.equal_range(3);
if (ret2.first != m.end())
{
cout << "找到了equal_range中的lower_bound的key= " << ret2.first->first << "value=" << ret2.first->second << endl;
}
else
{
cout << "未找到" << endl;
}
if (ret2.second != m.end())
{
cout << "找到了equal_range中的upper_bound的key= " << ret2.second->first << "value=" << ret2.second->second << endl;
}
从大到小排列
//还是需要利用仿函数
class myCompareInt//仿函数的类
{
public:
bool operator()(int v1,int v2) const
{
return v1 > v2;
}
};
int main()
{
map<int, int, myCompareInt> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(3, 30));
m.insert(make_pair(2, 20));
m.insert(make_pair(4, 40));
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << (*it).first << " " << (*it).second << endl;
}
return 0;
}
//这就完成了g键值从大到小的