初识STL——set,multiset,map,multimap
来源:互联网 发布:redis数据库设计java 编辑:程序博客网 时间:2024/06/05 04:48
最近在学习STL,在前期分析了vector和list的源码,印象很深,感觉对自己以后的代码之路产生了很多改变,今天,介绍下STL当中的几个关联式容器。本博客所有论述的都为SGI版本的STL。
1.什么是关联式容器
关联容器是通过键存取和读取元素、顺序容器通过元素在容器中的位置顺序存储和访问元素。因此,关联容器不提供front、push_front、pop_front、back、push_back以及pop_back,此外对于关联容器不能通过容器大小来定义,因为这样的话将无法知道键所对应的值什么。
关联式容器分为set(集合)和map(映射表)两大类,还有拓展的multiset(多键集合)和multimap(多键映射表)。这些容器的底层实现都是使用了红黑树来实现的。
另外,STL还提供了hash_table(散列表),hash_set(散列集合),hash_map(散列映射表),hash_multiset(散列多键集合),hash_multimap(散列多键映射表)。这些都是利用hash表实现的。
总共9个容器。
另外来说,在C++11当中,新的标准重新定义了4个无序的关联式容器,就是unordered_map,unordered_set,unordered_multiset,unordered_multimap,
所以在介绍容器之前你首先应该有红黑树的知识,不熟悉可以翻一下前面的博客,对平衡树方面都有论述!
2.set
我们首先来看set,重点来熟悉一下set的接口。
这些接口当中,很多我们使用很简单,比如像是关于容量的接口。
在这我们说下insert。
pair<iterator,bool> insert ( const value_type& x ); iterator insert ( iterator position, const value_type& x );template <class InputIterator> void insert ( InputIterator first, InputIterator last );
这里面的pair就是一个key-value的结构体。这个结构体的定义是这样的:
template<typename K,typename V>struct pair{ K first; V value;}
在这里因为value是不存在的。所以返回以后的first就是迭代器,value就是bool类型。
我们可以通过测试:
std::set<int> num; cout << num.empty() << endl; num.insert(1); num.insert(5); pair<set<int>::iterator,int > ret1= num.insert(23); num.insert(ret1.first, 12); pair<set<int>::iterator, int >ret = num.insert(5);
在这,我们的insert有两种情形,一种插入的是不存在set中的,另外一种是存在set中的,对于不存在的,返回的pair是返回插入的迭代器,bool返回true,对于存在的,返回的pair是返回已经存在的迭代器,bool返回false。
然后再来看erase,
void erase ( iterator position );size_type erase ( const key_type& x ); void erase ( iterator first, iterator last );
erase函数返回一个size_type,其实就是你的bool,如果你的这个是存在的,那么返回就是true,如果不存在,那么就返回false。
剩下的两个没有太大难处,一个需要讨论的是find。
对于find,
iterator find ( const key_type& x ) const;
我们需要注意,find返回的是const的迭代器,如果找到了,就返回x所在的迭代器,如果没有找到,那么就返回的是end()。在我们输出这些上,要特别注意这一点,因为end()不是你的有效空间,防止对它进行访问引起不必要的错误。
3.multiset
multiset是一个多键集合,对于这个多键集合而言,就是调用了底层实现红黑树的不同的一个insert,在set中是如果insert,先进行查找,这个时候如果存在那么就结束查找,返回pair的boolfalse。现在是如果存在,那么就继续插入,至于插入红黑树的那一边,其实都是一样的,对于它的性能是一样的。
对于multiset而言来说,改变的是insert。
iterator insert ( const value_type& x );iterator insert ( iterator position, const value_type& x );template <class InputIterator> void insert ( InputIterator first, InputIterator last );
在插入的时候返回的是一个迭代器,因为可以出现重复的key。
erase
void erase ( iterator position );size_type erase ( const key_type& x ); void erase ( iterator first, iterator last );
erase所操作的是删除了所有相同键值的节点。这里返回的size_type其实就是删除的重复的个数。如果不存在那么返回的当然是0。
find
iterator find ( const key_type& x ) const;
和set一样,返回迭代器,这里如果存在一样的,那么只是返回第一个迭代器。
在这里说一下count
size_type count ( const key_type& x ) const;
这个count在set和count中都存在,在set中,它只会返回 1或者0,但是在multiset当中,它返回的数目就会是其他了。
其他的不是太为常用,如果想要自己研究看文档就好了,我就介绍这些。
4.map
map而言,map所使用的结构是key—value。在这里就是一个pair。
pair第一个元素是key,第二个元素是value。
template<typename K,typename V>struct pair{ K key; V value;}
每一个节点都是这样的一个结构体,然后存在一棵红黑树当中的。
同样的,对于一些很简单看文档就能了解的我们就不多说了,关注一些比较有太大区别的。
map的insert实现,因为保存的是每一个pair这样的结构体,所以如果要插入,你也应该插入这样的结构体才对。
我们先来看库所提供的接口:
pair<iterator,bool> insert ( const value_type& x ); iterator insert ( iterator position, const value_type& x );template <class InputIterator> void insert ( InputIterator first, InputIterator last );
所以我们使用的时候,一定要按照规则来使用。
这个里面,你所构造的pair和insert返回的pair是两个东西,一个是向map中所要插入的结构体,一个是返回说明map当中是否存在你所要插入的键值相同的结构体。
std::map<int,string > footballmap; //插入的是一个pair类型的结构体,用后面()中的内容初始化构造对象。然后插入进去。 footballmap.insert(pair<int, string>(1, "西班牙")); footballmap.insert(pair<int, string>(2, "德国")); footballmap.insert(pair<int, string>(3, "葡萄牙")); footballmap.insert(pair<int, string>(4, "意大利")); footballmap.insert(pair<int, string>(5, "巴西")); footballmap.insert(pair<int, string>(6, "法国")); pair<map<int, string>::iterator, bool > a = footballmap.insert(pair<int, string>(1, "阿根廷"))
上述例子运行以后,你可以看到,插入的键值为1,这个时候你的value依然为“西班牙”,这是因为,在这个时候联想红黑树插入的原理,我们首先进行查找键值为1的节点,找到了节点,那么就返回一个pair结构体,pair结构体的first为键值为1的节点的迭代器,second是个bool,为true代表插入成功,false代表以及存在相同键值的节点 ,插入失败。
既然这样,我们不仅要想一下,我们如何来修改这个键值的value呢?
我们其实就可以通过insert的返回值来进行修改。上面a是一个保存了键值的迭代器,和bool值得一个pair结构体。
所以我们可以通过pair结构体修改value。
a.first->second = "阿根廷";
这样就更改了键值为1的value。
或者我们还可以通过find函数先找到
find的接口:
iterator find ( const key_type& x );const_iterator find ( const key_type& x ) const;
find返回的是一个迭代器,这个迭代器我们可以理解为pair的一个指针,然后我们就可以通过这个指针来修改这个结构体中的内容。
比如:
map<int, string>::iterator i = footballmap.find(1); i->second = "中国";
这样我们也实现了修改。
当然,库中其实也为我们想到了这一点,给我们封装了一个接口函数,
它就是:operator[]
我们当然可以使用operator[]进行修改,operator []的内部实现就是
(*((this->insert(make_pair(x,T()))).first)).second
其实就是insert找到以后的,这个返回的pari的第一个迭代器的第二个元素,就是value。
这样我们就实现了修改了。
然后看下erase,erase一样,返回的依然是删除的个数,删除迭代器,和键值的节点。
void erase ( iterator position );size_type erase ( const key_type& x ); void erase ( iterator first, iterator last );
其他的和上述的set,multiset是一样的。
5.multimap
对于multimap而言,其实和map的大部分也是一样的。
、
它可以允许重复的key出现。
比如
multimap<int, string> nummap; nummap.insert(pair<int, string >(1, "白菜")); nummap.insert(pair<int, string >(1, "番茄")); nummap.insert(pair<int, string >(1, "胡萝卜")); nummap.insert(pair<int, string >(2, "菠菜")); nummap.insert(pair<int, string >(3, "南瓜"));
这个里面就会储存相同键值为1的三个pair。
调用erase一样是删除所有相同键值的节点。
它没有operator[],所以如果你要修改,那么就必须采用迭代器,然后修改的方式了。
- 初识STL——set,multiset,map,multimap
- STL 之 初识set multiset(map multimap)
- STL map, multimap, set, multiset 函数介绍
- STL容器 set、 multiset、map、multimap
- C++ STL之 map\set\multimap\multiset
- STL — 从源码层面区别map set和multiset multimap
- map,multimap,set,multiset
- set,map,multiset,multimap
- map,multimap,set,multiset
- map/multimap/set/multiset
- 【STL】STL中红黑树的应用set、multiset、map、multimap
- STL概览-关联容器set,multiset,map,multimap(四)
- STL set multiset map multimap unordered_set unordered_map example
- STL源码剖析之map set multimap multiset【2013.12.10】
- stl中的map、set、multimap、multiset,兼谈OceanBase造轮子
- STL中HashTable HashMap HashSet Set Map MultiSet MultiMap总结
- STL有4种联合容器(set,multiset, map, multimap)
- STL总结之set/multiset和map/multimap
- 微信小程序(应用号)开发你一定要知道的一些细节
- Java---Which four statements are true
- 缓冲区溢出
- LeetCode 148. Sort List
- jquery 删除动态创建的table中的tr
- 初识STL——set,multiset,map,multimap
- 写好自己的模板方法,以后要做的就是对于模板方法进行具体化了
- PHP入门
- ehcache2.5后hibernate多SessionFactory报错的解决
- Service
- Linux编程磁盘管理基本命令
- hdu3555 数位dp
- 《python+opencv实践》四、图像特征提取与描述——29理解图像特征
- MySQL在大型网站的应用架构演变