C++的关联容器主要是两大类map和set
我们知道谈到C++容器时,我们会说到 顺序容器(Sequence containers),关联容器(Associative containers),无序关联容器(Unordered associative containers)以及容器适配器(Container adaptors),
另外,我相信,这些抽象的容器概念,应该是所有高级语言都有的。本文重点阐述关联容器。
Associative containers implement sorted data structures that can be quickly searched (O(log n) complexity).
关联容器实现了可以快速搜索(O(log n)复杂度)的排序数据结构。
主要就是 set、map、multiset和multimap。
std::map
map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Maps are usually implemented as red-black trees。
map是一个排序的关联容器,它包含具有惟一键的键值对。通过使用Compare函数对键进行排序。搜索、删除和插入操作具有对数复杂度。映射通常被实现为红黑树
理解map需要理解键值对、有序、键值唯一以及对数级别的操作。
键值对
既然是关联容器,那自然要关联下,这里的关联就是key和value的关联,通过
std::map<string,string> mapStr;
这样,我们就定义了一个key为string ,value为string的map。我们可以通过中括号直接给键值对赋值:mapStr["name"] = "lckfa"; mapStr["sexuality"] = "male";
事实上,map的底层是使用pair来实现的,std::pair是一个结构模板,它提供了一种将两个异构对象存储为单个单元的方法。因此还可以使用如下代码完成上面的操作:
pair<string,string> pair1("name","lckfa"); pair<string,string> pair2("sexuality","male"); mapStr.insert(pair1); mapStr.insert(pair2);
有序
为了看看map是怎么有序的,我们先弄个打印函数出来
template<typename Map> void print_map(Map& m){ std::cout << "{ " ; for_each(m.begin(),m.end(),[&](Map::value_type& p){ std::cout << p.first <<":"<<p.second<<' '; }); std::cout << "}" ; }
这个打印函数模板,可以打印任何类型的map。这下再也不担心map的类型改变了。还不会使用labmda表达式的,可以去看我的另一篇博文,另外value_type可以理解为pair,这里和Map是一个类型。
然后,我们在之前的map里新增一个键值对
mapStr["sss"] = "sss"; mapStr["aaa"] = "aaa"; mapStr["bbv"] = "bbb";
使用pair,然后insert也行。
然后调用
print_map
函数,结果如下:{ aaa:aaa bbv:bbb name:lckfa sexuality:male sss:sss }
以上结果充分说明 map是按key的升序排列的。
备注,如果你想自定义map的排序方式,可以参考这里
键值唯一
白话就是,这里的key值总是唯一的,那么让我们来验证下,同时向map里插入相同键值会发生什么:
mapStr["name"] = "lckfa"; mapStr["sexuality"] = "male"; mapStr["name"] = "mal9";
打印结果:
{ name:mal9 sexuality:male }
从结果可知,再重新设置某个key的value后,后一个会覆盖前一个value。
对数级别的复杂度操作
这个就不展开了,有兴趣的可以了解一个红黑树。
std::set
std::set is an associative container that contains a sorted set of unique objects of type Key. Sorting is done using the key comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Sets are usually implemented as red-black trees
set是一个关联容器,它包含一组类型为Key的已排序的惟一对象。排序是使用key的比较函数比较来完成的。搜索、删除和插入操作具有对数复杂度。集合通常被实现为红黑树。
和map一样,除了map的键值对差异,set只有key,这样的差异外,set和map再定义和使用上没有很大的差异。同样的set也具有 key唯一,有序,对数复杂度的特点,这里使用一个统一的代码说明下:
template<typename Set>
void print_set(Set& s){
cout << "{ ";
for_each(s.begin(),s.end(),[&](Set::key_type k){
std::cout << k <<' ';
});
std::cout << "}" ;
}
std::set<int> setInt;
setInt.insert(4);
setInt.insert(2);
setInt.insert(5);
setInt.insert(2);
std::set<string> setStr;
setStr.insert("hello");
setStr.insert("set");
setStr.insert("world");
setStr.insert("set");
print_set(setInt);
print_set(setStr);
测试输出结果:
{ 2 4 5 }{ hello set world }
由结果可知:set的key值也是唯一的,同时按升序排列,如果希望自定义排列,需要需改比较函数。
小结:本文初略的整理了map和set的基础使用,说明了二者的特性,key唯一,有序,算法对数级。仅仅能作为初学者参考。