本科教育忽略的黄金C++<2> 顺序容器

本文深入探讨了C++中顺序容器的使用及其内部实现,包括vector、deque、list、forward_list、array和string容器的特性、性能折中、构造函数、访问元素、删除元素和改变容器大小等操作。详细介绍了如何选择合适的容器以优化程序性能。

顺序容器:为程序员提供了控制元素存储和访问顺序的能力。

1、顺序容器概述

容器以下方面都有不同的性能折中:
向容器中添加和删除元素的代价。
非顺序访问容器中元素的代价。

vector:可变大小数组。在尾部之外的位置插入或删除元素效率低下。
deque:双端队列,支持快速随机访问。头尾位置插入删除速度很快。
list:双向链表,任何位置删除插入都很快。
for_ward:但向链表,只支持单向顺序访问。在链表的任何位置进行插入删除操作速度都很快。
array:固定大小数组,支持快速随机访问,不能添加和删除元素。
string:和vector相似的容器,但是专门用于保存字符。随机访问快。尾部插入删除速度快。

vector,string容器原理
元素连续存储,由元素下标计算非常快速。但是在这两种容器的中间位置添加或者删除会非常浪费时间。
list,for_ward容器原理
令容器任何位置的添加和删除都很快速,但是,不支持元素的随机访问。

一些小策略:
如果程序只有在读取输入的时候要求在容器中间插入元素,随后需要随机访问元素:
在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。

2、容器库详述

分类:所有容器类型都支持的,针对顺序容器的,针对无序容器的,针对关联容器的。

本文介绍通用容器库和针对顺序容器的容器库。

一般来说,每个容器都定义在一个头文件中,文件名和类型名相同。

关于容器保存的元素限制:
顺序容器几乎可以保存任意类型的元素。
注意,在创建自定义类的容器,需要给容器提供默认构造函数。

vector<myclass> v1(10,init);

通用容器操作:
<类型别名>
iterator:此容器类型的迭代器类型。
const_iterator:可以读取元素但是不能够修改元素的迭代器。
size_type:无符号整数,足够保存此种类型容器最大可能的容器大小。
difference_type:带符号整数类型,足够保存两个迭代器之间的距离。
value_type:元素类型。在不了解容器中元素类型的情况下使用。
reference:元素的左值类型。和value_type&含义相同。元素类型引用。
const_reference

<构造函数>
C c;默认构造函数
C c1(c2);拷贝构造函数。两个容器的类型以及元素类型必须匹配。
C c(a,b);拷贝两个迭代器之间的内容。就不要求容器类型是相同的了。
C c(a,b,c……);列表初始化。

只有顺序容器不包括array才能够接受大小参数:
C seq(n):才能构建一个包含n个元素的容器。
C seq(n,t):创建n个值为t的容器。
标准库array具有固定大小
array

list<string>lst;
auto iter=lst.begin();
while(cin>>word)
    iter=lst.insert(iter,word);

当我们调用一个emplace成员函数的时候,是将参数传递给元素类型的构造函数。使用这些参数在容器管理的内存空间中直接构造元素。

c.emplace("90901820",25,15.99);
//实际上是线调用c中存储的数据类型之后创建一个对象,然后将这个对象插入到c容器中。

emplace函数在容器中直接构造元素。传递给emplace函数的参数必须与元素类型的构造函数相匹配。

<访问元素>
at和下标操作只适用于string,vector,deque,array.back不适合forward_list
c.back():返回c中尾元素的引用。若c为空,函数行为未定义。
c.front():返回c中首元素的引用。
c[n]:返回下标为n的元素的引用。
c.at(n):同上。

<删除元素>
删除操作会改变容器的大小,不适合array容器。forward_list有其他版本的erase,不支持pop_back。vector和string不支持pop_front
c.pop_back():删除c中的尾元素,如果c为空,则函数行为未定义。函数返回void。
c.pop_front():删除c中的首元素。
c.erase(p):删除迭代器p所指定的元素,返回一个指向被删除元素之后元素的迭代器。如果p指向尾元素。则返回尾后迭代器。若p为尾后迭代器,则函数行为未定义。
c.erase(b,e):删除迭代器b,e所指定范围内的元素。返回一个指向最后一个被删除元素之后元素的迭代器。注意e,指向我们要删除的最后一个元素之后的位置。
c.clear():删除所有元素。

<改变容器大小>
c.resize(n):调整c的大小为n个元素。若n

stack <int> skt(deq);//从deq拷贝元素到stk。定义一个适配器。

默认情况下,stack和queue是基于deque实现的,priority_queue是在vector之上实现的。我们可以创建一个适配器的时候讲一个命名的顺序容器作为第二个类型参数。来重载默认容器类型。

stack <string,vector<string>> str_stk(svec);

对于一个给定的适配器,可以使用哪些容器是有限制的。

<关于栈的相关操作>
s.pop():删除栈顶元素。
s.push(item):创建一个新元素压入栈顶,该元素通过拷贝或者移动item而来或者由args构造。
s.emplace(args)
s.top():返回栈顶元素,但是不弹栈。

<关于队列适配器>
q.pop():返回queue的首元素或priority_queue的最高优先级的元素。但是不删除这个元素。
q.front():返回首元素或者尾元素但是不删除这个元素。
q.back()
q.top():返回优先级最高的元素,但是不删除该元素。
q.push(item):在queue末尾或者priority_queue中恰当位置创建一个元素,其值为items,或者由args构造。
q.emplace(args)

queue使用一种先进先出策略。FIFO。priority_queue允许我们为队列中的元素建立优先级。新加入的元素会排在所有优先级比它低的已有元素之前。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值