C++关联容器

来源:互联网 发布:淘宝网购支付宝限额 编辑:程序博客网 时间:2024/06/06 00:30

1.关联容器是通过关键字来保存和访问数据的。关联容器分为两大类:map和set。其中,map是通过键值对来操作的,这里的键就是关键字,值就是对应的数据。

例如:

map<int ,int> m;定义了一个空的map变量m,它的关键字类型是int,关键字对应的值的类型是int。可以将map理解成为函数,关键字是自变量,关键字对应的值是因变量。

set,这是一个集合类。它的关键字和值是相同的。也就是说定义了一个set,它的关键字和值是同一个值。例如:

set<int> s;定义了一个空的set类型的变量s,它里面可以存储int类型的数据,它的关键字和值都是同一个,类型都是int。set和数学上的集合是一样的,都有一个特点,唯一性。也就是说,set中的元素,一般不能重复出现。因此,我们有时候使用set,来判断一个关键字是否在一个某一个集合中。

2.map和set有很多种类:它们通过前面的修饰词来加以区分。修饰词主要有:unordered,multi,一个表示无序,另外一个表示关键字可以重复。例如:unordered_multiset表示,一个无序的,关键字可以重复的set。这里的无序的实现数据结构是哈希函数。

map和set都是模板。

3.关于定义关联容器,可能当你去读C++ primer这本书时,会发现,在定义关联容器时有好多方法。其实,通过我的时间发现,这和你的编译环境,编译器是有很大的联系的,又看看,你的编译器对C++11支持多少。

例如:

定义:map<string,string> word={ {"A","a"},{"B","b"}};//对于这样的定义,不同的编译器,编译之后的结果也是不一样的。想VS2012好像就不能支持。

4.因为,关联容器的关键字和对应值的类型,没有强制的限制,也就是说,自己定义的类也可以当做关键词或者对应的值的类型来使用,但是,我们要注意,无论哪一种类型,要支持比较运算符<,或者要支持比较方法。如果不支持,麻烦自定义。

5.pair类型:

在之前我们说cocos2dx中读取excle文件时,最后提到了pair类型,这里我们对其进行更加详细的说明。

pair类型,这是一个标准库类型。pair类型,保存两个数据,在初始化的时候,需要传递两个类型。pair的两个数据成员是公共的。

6.关联容器的操作:

6.1额外的类型别名:

value_type:对于set来说,这个和关键字的类型是一样的。对于map来说,这个的类型是:pair<const key_type,mapped_type>

例如:

map<int ,int >::value_type var;//var的类型就是pair<const int,int>。

mapped_type:每个关键词关联的类型。这个只使用与map,说白了,就是值的类型

例如:map<int ,int >::mapped_type var;//var的类型就是int

key_type:就是关键字的类型

6.2关于map的操作.

6.2.1要向map中添加元素,这个元素的类型,必须是pair类型。正如上面所说的,map中value_type是pair类型。因此,就像之前讲过的,要构造一个pair类型的数据,例如:make_pair<i,j>这就是构造一个pair类型的数据。

例如:

map<int,int> m1;//不能重复关键字auto it=m1.begin();map<int ,int>::key_type i;int j=10;for(int i=0;i<10;i++){auto p=m1.insert(make_pair(i,j));j++;}
添加元素,使用函数insert()。


但是,要特别注意:insert的返回值问题。

template<class _Valty>typename enable_if<is_convertible<_Valty, value_type>::value,_Pairib>::typeinsert(_Valty&& _Val){// try to insert node with value _Val, favoring right side_Nodeptr _Newnode = this->_Buynode(_STD forward<_Valty>(_Val));return (_Insert_nohint(false,this->_Myval(_Newnode), _Newnode));}
上面是insert的源码。编译环境VS2012

insert返回的值依赖于容器类型和参数。

如果是关键字不能重复的,insert返回一个pair类型值。这个值的first数据成员保存的是一个指向要插入元素的迭代器,second数据成员,是一个bool值,用来表示要插入的值,是否插入成功。

例如:

map<int,int> m1;//不能重复关键字auto it=m1.begin();map<int ,int>::key_type i;int j=10;for(int i=0;i<10;i++){auto p=m1.insert(make_pair(i,j));if(p.second)cout<<"插入的值:"<<p.first->second<<endl;j++;}
在这段代码中,我们将i,j插入到map中。在这里,p的类型就是一个pair类型.first数据成员,是一个迭代器,指向插入元素的一个迭代器。这个迭代器中,存放的就是要插入的这两个数i和j的值。p的second元素是一个bool类型的数据,表示是否插入成功。

这段代码,单步调试的结果:


最后的结果值:


6.2.2其次,就是迭代器的问题。

当解引用一个关联容器的迭代器是,我们将得到一个值的value_type的一个引用。

在map中,value_type是一个pair。而且,first还是const类型的,所以,不能修改first指向的数据。

在set中,set和map差不多,也是只能读取,不能修改。

例如:

for(auto it=m1.begin();it!=m1.end();it++){cout<<"first:"<<it->first<<"second:"<<it->second<<endl;
要注意,当使用迭代器遍历map和set时,迭代器是按照关键字的升序顺序来遍历的。

6.2.3 删除元素。

删除元素,使用ereas函数,传入的参数可以是关键字,迭代器,迭代器的范围。也就是说,通过这个函数,可以删除一个范围的元素。

例如:

m1.erase(1);//删除对应关键词的元素

这一步操作之后,会将关键字为1,这个键值对删除。

6.2.4下标运算符和访问元素

map是可以支持下标运算符的。set是不支持下标运算符的。

例如,之前定义的m1这个变量,如果,我们这样操作:m1[11]。显然,我们没有11这个关键字,但是如果使用下标运算符之后,他会将11这个关键字添加到m1这个map中,而且,还会初始化。

因此,我们要知道,一个关键字,是否在一个map中,最好使用find和cout函数。

这两个函数的源码:

// 返回关键字的个数//size_type count(const key_type& _Keyval) const//{// count all elements that match _Keyval//_Paircc _Ans = equal_range(_Keyval);//size_type _Num = 0;//_Distance(_Ans.first, _Ans.second, _Num);//return (_Num);//}p.count(1);
count这个函数,是判断这个关键字在map中,是否存在,而且,存在几个。

//这个函数适合检查该元素是否在关联容器中,传递的参数是关键词的类型//源码//iterator find(const key_type& _Keyval)//{// find an element in mutable sequence that matches _Keyval//iterator _Where = lower_bound(_Keyval);//return (_Where == end()//|| _DEBUG_LT_PRED(this->_Getcomp(),//_Keyval, this->_Key(_Where._Mynode()))//? end() : _Where);//}auto temp= p.find(1);

find函数,只关心关键字是否存在在map中。


这就是今天我们要和大家分享的关于C++关联容器的知识,欢迎大家指正!



0 0
原创粉丝点击