文章目录

  • ​​set/multiset容器​​
  • ​​set/multiset对象的构造​​
  • ​​set/multiset的常规操作​​
  • ​​set/multiset其他操作​​
  • ​​map\multimap容器​​
  • ​​map/multimap构造函数​​
  • ​​map/multimap元素访问​​
  • ​​map/multimap修改​​
  • ​​insert​​
  • ​​earse​​
  • ​​map操作​​

set/multiset容器

set是一个集合容器,其中所包含的元素是唯一的,集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。

set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树。在插入操作和删除操作上比vector快。

multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。

不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。

set/multiset对象的构造

set();
set(const set& _Right);
explicit set(const key_compare& _Pred);
set(_Iter _First, _Iter _Last);
set(_Iter _First, _Iter _Last, const key_compare& _Pred);

set/multiset的常规操作

bool empty();
size_t size();
size_t max_size();

pair<iterator, bool> insert(const value_type& _Val);
iterator insert(const value_type& _Val);
void insert(_Iter _First, _Iter _Last);
void insert(initializer_list<value_type> _Ilist);

iterator erase (const_iterator where); //返回下一个元素的位置
size_type erase (const value_type& val); //返回删除元素的个数,对于set来说,永远是1(set的值不能重复)
iterator erase (const_iterator first, const_iterator last); //区间删除

void swap(const &right); //交换set
void clear(); //清空所有元素
template <class... _Valtys>
pair<iterator, bool> emplace(_Valtys&&... _Vals);

//提示从whrere开始找,不是插入到where的位置,如果vals满足排在where指向的值的后面,那么将提高速度,否则无影响
template <class... _Valtys>
iterator emplace_hint(const_iterator _Where, _Valtys&&... _Vals)

代码示例:

int main()
{
//multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
set<int> a{ 1,1,2,2,3,3,4,5,6 };
multiset<int> b{ 1,1,2,2,3,3,4,5,6 };
cout << "set容器的删除永远返回:" << a.erase(1) << endl;
cout << "multiset容器的删除可以有多个:" << b.erase(1) << endl;
/*
set: 1 2 3 4 5 6
multiset: 1 1 2 2 3 3 4 5 6
*/

for (auto& x1 : a)
{
cout << x1 << " ";
}
cout << endl;
for (auto& x2 : b)
{
cout << x2 << " ";
}
cout << endl;
return 0;
}

C++ STL 关联式容器操作总结_数据结构


set/multiset其他操作

有关算法的操作,我将会在算法那一节集中讲解。

//两个返回的都是一样的
key_compare key_comp()const;
value_compare value_comp()const;

iterator find(const key_type& _Keyval);//在容器中搜索与val等效的元素,如果找到则返回一个迭代器,否则返回end迭代器。
size_t count(const key_type& _Keyval); //在容器中搜索与val等效的元素,并返回匹配数。

//与排序规则有关
iterator lower_bound(const key_type& _Keyval);//找到第一个大于或者等于keyval的值
iterator upper_bound(const key_type& _Keyval);//找到第一个大于keyval的值

pair<iterator, iterator> equal_range(const key_type& _Keyval)

map\multimap容器

map(映射)是关联容器,用于存储按特定顺序由键值映射值的组合形成的元素,即(key,value)对。它提供基于key的快速检索能力。

map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。

map的具体实现采用红黑树变体的平衡二叉树的数据结构。在插入操作和删除操作上比vector快。

map可以直接存取key所对应的value,支持[]操作符,如map[key]=value。

multimap与map的区别:map支持唯一键值,每个key只能出现一次;而multimap中同一key可以出现多次。map支持[]操作符,但是multmap不支持

map <string, int> a{ {"喜羊羊",2},{"喜羊羊",2},{"虎太郎",3},{"懒洋洋",10} };
multimap <string, int> a1{ {"喜羊羊",2},{"喜羊羊",2},{"虎太郎",3},{"懒洋洋",10} };

map不可以出现重复的key,multimap允许

C++ STL 关联式容器操作总结_c++_02

map/multimap构造函数

map();
map(const map& _Right);
map(const key_compare& _Pred);
map(_Iter _First, _Iter _Last);
map(_Iter _First, _Iter _Last, const key_compare& _Pred);

注意:map的构造函数必须使用 {}来构造,因为map包含一个string和int,他们是一对 ​​键值对​​,一个关键字对应一个数值,他们是绑在一起的。
注意:map的返回值为一个pair类型。 pair类型有first和second成员,pair的first指向map的第一个数据类型,即string; pair的second指向map的第二个数据类型,即int类型,可以使用 . 运算符来访问:

pair<const string, int> aPoint;
map <string, int> a{ {"喜羊羊",2},{"虎太郎",3},{"懒洋洋",10} };
for (auto& x : a)
{
cout << x.first << ":" << x.second << endl;
}

map/multimap元素访问

mapped_type& operator[](key_type&& keyval); //根据key获取value
mapped_type& at(const key_type& _Keyval);

map支持 []运算符来访问元素,即[]里的是一个关键字,可以类似于数组,使用[]来指定关键字,然后找到其所包含的第二个数据,int。

cout << a["喜羊羊"] << " " << a["懒洋洋"] << endl;
cout << a.at("虎太郎") << endl;

C++ STL 关联式容器操作总结_键值对_03


map/multimap修改

insert

insert插入的是由键值对组成的pair<key_type,mapped_type>,可称为对组

key_type 键类型

mapped_type 值类型

value_type map装的元素内存,即pair<key_type,mapped_type>

pair<iterator,bool> insert (const value_type& val);
pair<iterator,bool> insert (value_type&& val);

假设 map<int, string> stu;

一、通过pair的方式插入对象

stu.insert(pair<int, string>(1, "maye"));

二、通过make_pair的方式插入对象

stu.insert(make_pair(2, "zoey"));

三、通过value_type的方式插入对象

stu.insert(map<int, string>::value_type(3, "lisa"));

四、通过数组的方式插入值

stu[3]= "取个名字好难";
stu[4] = "有人@我";

前三种方法,采用的是insert()方法,该方法返回值为pair<iter,bool>

iterator 指向插入的pair,bool标识是否插入成功

第四种方法非常直观,但存在一个性能的问题。

按key(3)插入元素时,若map中没有key(3),则键值对插入map,若key(3)已经存在,则修改key(3)对于的值。

string strName = stu[2];  //获取key对于的值

只有当stu存在2这个键时才是正确的取操作,否则会自动插入一个实例,键为2,值为初始化值。


总结:插入的几种方式

//通过pair来插入键值对
auto it=a.insert(pair<string, int>("熊大", 15));
cout <<"插入成功了吗?"<<boolalpha<<it.second<<"\t"<< it.first->first << ": " << it.first->second << endl;

//通过make_pair来插入键值对
it=a.insert(make_pair<string, int>("小灰灰", 55));
cout << "插入成功了吗?" << boolalpha << it.second << "\t" << it.first->first << ": " << it.first->second << endl;


//通过value_type来插入
it=a.insert(map<string, int>::value_type("熊二", 66));
cout << "插入成功了吗?" << boolalpha << it.second << "\t" << it.first->first << ": " << it.first->second << endl;


//通过数组方式插入
a["美羊羊"] = 666;
a["茶人"] = 999;

注意:insert插入的返回值为pair<iter,bool>

  • pair的第一个参数是iter,iter是一个指向map的一对键值对的pair,所以为了访问此元素,可以首先使用​​pair.first->first/second​​ 首先获取迭代器,然后再获取map的元素。
  • 插入后,他们的关键字会自动按照顺序排序,如图为首字母的顺序。

earse

//删除key为keyval的元素,返回删除成功的数量
size_t erase(const key_type& _Keyval);
//删除[first,last)区间元素,返回last
iterator erase(const_iterator _First, const_iterator _Last);
//删除where指向的元素,返回下一个元素迭代器
iterator erase(const_iterator _Where);

示例:

//删除关键字对应的键值对
a.erase("喜羊羊"); //返回size_t 即删除的个数
//删除区间
auto it1 = ++a.begin();
++it1;
++it1;
a.erase(a.begin(),it1);

首先会删除指定关键字的键值对,然后第二个接受一个区间,会删除区间里的内容。


emplace

//就地构造,传
template <class... Args>
pair<iterator,bool> emplace (Args&&... args);
template <class... Args>
iterator emplace_hint (const_iterator position, Args&&... args);
//stu.emplace(12, "duck"); //key,mapped

map操作

void clear();
bool empty();
size_t size();
size_t max_size();

//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
iterator find(const key_type& _Keyval);

//返回容器中key为keyval的pair个数,对于map要么是0,要么是1。对multimap来说,值可能大于1。
size_type count(const key_type& _Keyval);

iterator lower_bound(const key_type& _Keyval);
iterator upper_bound(const key_type& _Keyval);
//返回
pair<iterator, iterator> equal_range(const key_type& _Keyval);