C++中容器总结

[转自]http://www.jb51.net/article/70341.htm#

C++中的容器大致可以分为两个大类:顺序容器和关联容器。顺序容器中有包含有顺序容器适配器。
顺序容器:将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素。主要有vector、list、deque(双端队列)。顺序容器适配器:stack、queue和priority_queue。
关联容器:支持通过键来高效地查找和读取元素。主要有:pair、set、map、multiset和multimap。
接下来依次对于各种容器做详细的介绍:
一、顺序容器:
1、顺序容器定义
为了定义一个容器类型的对象,必须先包含相关的头文件:
定义vector:#include
定义list:#include
定义deque:#include
实例:
vectorv1;//定义一个vector v1,v1中每个元素都是int类型;
listl1;//定义一个list l1,l1中每个元素都是int类型;
dequed1;//定义一个deque d1,d1中每个元素都是int类型;
2、顺序容器初始化:
这里写图片描述
3、顺序容器支持的指针运算
(1)所有顺序容器都支持指针运算
这里写图片描述
(2) vector 和 deque 容器的迭代器提供额外的运算
这里写图片描述
(3)迭代器失效:一些容器操作会修改容器的内在状态或移动容器内的元素。这样的操作使所有指向被移动的元素的迭代器失效,也可能同时使其他迭代器失效。使用无效迭代器是没有定义的,可能会导致与悬垂指针相同的问题。
(4)begin和end成员:begin和end操作产生指向容器内第一个元素和最后一个元素的下一位置的迭代器。
这里写图片描述
3、顺序容器操作
(1)添加元素
这里写图片描述
(2)容器的大小操作
这里写图片描述
(3)访问元素
这里写图片描述
(4)删除元素
这里写图片描述
(5)赋值与swap
这里写图片描述
swap示例:

vector<string> vs1(3); // vs1有3个元素
vector<string> vs(5); // vs2有5个元素
vs1.swap(vs2);//执行后,vs1中5个元素,而vs2则存3个元素。

(6)vector的自增长:capacity 和 reserve 成员
为了提高vector的效率,不用每次添加元素都重新分配空间。vector会在分配空间时候预分配大于需要的空间。vector 类提供了两个成员函数:capacity 和reserve 使程序员可与 vector 容器内存分配的实现部分交互工作。
capacity操作:获取在容器需要分配更多的存储空间之前能够存储的元素总数
reserve操作:告诉vector容器应该预留多少个元素的存储空间
capacity(容量)与size(长度)的区别:size指容器当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。capacity一般情况下 是比size大的。
可以通过函数reserve()来操作预留空间

vec.reserve(vec.capacity()+50);//为vec增加了50的预留空间

另外:如果不手动操作来预留空间,每当 vector 容器不得不分配新的存储空间时,以加倍当前容量的分配策略实现重新分配。
4、容器的选用
选择容器类型的常规法则:
(1)如果程序要求随机访问元素,则应使用 vector 或 deque 容器。
(2)如果程序必须在容器的中间位置插入或删除元素,则应采用 list 容器。
(3)如果程序不是在容器的中间位置,而是在容器首部或尾部插入或删除元素,则应采用 deque 容器。
(4)如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑在输入时将元素读入到一个 list 容器,接着对此容器重新排序,使其适合顺序访问,然后将排序后的 list 容器复制到一个 vector容器。
如果程序既需要随机访问又必须在容器的中间位置插入或删除元素,选择何种容器取决于下面两种操作付出的相对代价:随机访问 list 容器元素的代价,以及在 vector 或 deque 容器中插入/删除元素时复制元素的代价。通常来说,应用中占优势的操作(程序中更多使用的是访问操作还是插入/删除操作)将决定应用什么类型的容器。
5、容器适配器
(1)适配器通用的操作和类型
这里写图片描述
(2)适配器的初始化
所有适配器都定义了两个构造函数:默认构造函数用于创建空对象,而带一个容器参数的构造函数将参数容器的副本作为其基础值。
默认的stack和queue都基于deque容器实现,而priority_queue则在vector容器上实现。
示例:

vector<int> vi;
deque<int> deq;
stack<int> stk(deq); //用deq初始化stk
stack<int> stk1(vi); //报错

(3)适配器的操作
①栈适配器:

这里写图片描述
②队列和优先级队列:
这里写图片描述
二、关联容器
1、pair
(1)pair提供的操作:
这里写图片描述
(2)pairs类型定义和初始化
pair

map<string, int> word_count;

这个语句定义了一个名为 word_count 的 map 对象,由 string 类型的键索引,关联的值则int型。
map访问:对迭代器进行解引用时,将获得一个引用,指向容器中一个pair

word_count.insert(map<string, int>::value_type("Anna", 1));
word_count.insert(make_pair("Anna", 1));

insert的返回值:包含一个迭代器和一个bool值的pair对象,其中迭代器指向map中具有相应键的元素,而bool值则表示是否插入了该元素。如果该键已在容器中,则其关联的值保持不变,返回的bool值为true。在这两种情况下,迭代器都将指向具有给定键的元素。

pair<map<string,int>::iterator,bool>ret=word_count.insert(make_pair(word, 1));

ret存储insert函数返回的pair对象。该pair的first成员是一个map迭代器,指向插入的键。ret.first从insert返回的pair对象中获取 map 迭代器;ret.second从insert返回是否插入了该元素。
(6)查找并读取map中的元素
map中使用下标存在一个很危险的副作用:如果该键不在 map 容器中,那么下标操作会插入一个具有该键的新元素。所以map 容器提供了两个操作:count 和 find,用于检查某个键是否存在而不会插入该键。

这里写图片描述
(7)map对象中删除元素
这里写图片描述
3、set
①set容器的定义和使用
set 容器的每个键都只能对应一个元素。以一段范围的元素初始化set对象,或在set对象中插入一组元素时,对于每个键,事实上都只添加了一个元素。

vector<int> ivec;
for (vector<int>::size_type i = 0; i != 10; ++i) {
ivec.push_back(i);
ivec.push_back(i);
}
set<int> iset(ivec.begin(), ivec.end());
cout << ivec.size() << endl; //20个
cout << iset.size() << endl; // 10个

②在set中添加元素

set<string> set1;
set1.insert("the"); //第一种方法:直接添加
set<int> iset2;
iset2.insert(ivec.begin(), ivec.end());//第二中方法:通过指针迭代器

③从set中获取元素
set 容器不提供下标操作符。为了通过键从 set 中获取元素,可使用 find运算。如果只需简单地判断某个元素是否存在,同样可以使用 count 运算,返回 set 中该键对应的元素个数。当然,对于 set 容器,count 的返回值只能是1(该元素存在)或 0(该元素不存在)

set<int> iset;
for(int i = 0; i<10; i++)iset.insert(i);
iset.find(1) // 返回指向元素内容为1的指针
iset.find(11) // 返回指针iset.end()
iset.count(1) // 存在,返回1
iset.count(11) // 不存在,返回0

3、multimap 和 multiset
关联容器 map 和 set 的元素是按顺序存储的。而 multimap 和multset 也一样。因此,在multimap和multiset容器中,如果某个键对应多个实例,则这些实例在容器中将相邻存放。迭代遍历multimap或multiset容器时,可保证依次返回特定键所关联的所有元素。
迭代器的关联容器操作:

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值