c++11の顺序容器

 容器是一种容纳特定类型对象的集合。C++的容器可以分为两类:顺序容器和关联容器。顺序容器的元素排列和元素值大小无关,而是由元素添加到容器中的次序决定的。标准库定义了三种顺序容器的类型:vector、list和deque(双端队列)。此外,标准库还提供了三种容器适配器:stack、queue和prioroty_queue类型。适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。见下表

复制代码
顺序容器
vector                    支持快速随机访问
list                      支持快速插入/删除
deque                     双端队列
顺序容器适配器
stack                     后进先出(LIFO)栈
queue                     先进先出(FIFO)队列
priority_queue            有优先级管理的队列
复制代码

一.定义和初始化

  定义一个容器类型的对象之前,必须包含相关的头文件。如下:

#include<list>
#include<vector>
#include<deque>

  所有容器都定义了默认构造函数,可以用默认构造函数来初始化一个空的容器对象,如下:

list<int>    ilist;

  此外,容器还有几种构造函数,可以用来初始化容器对象,如下:

C<T>    c         创建一个名为c的空容器。C是容器名,T是元素类型。适用于所有容器
C    c(c2)        创建容器c2的副本c。两者必须是相同类型的容器和元素。适用于所有容器
C    c(b,e)       创建c,其元素是迭代器b和e标记范围内元素的副本。适用于所有容器
C    c(n,t)       用n个值为t的元素创建c,其中t必须是容器类型C的元素类型的值或者是可以转化为该类型的值。只适用于顺序容器
C    c(n)         创建n个初始化元素的容器c。只适用于顺序容器

  值得注意到是,接受容器大小做形参的构造函数只适用于顺序容器,不适用于关联容器。由于指针就是迭代器,因此我们还可以通过使用内置数组中的一对指针初始化容器:

char *words[]={"Hi","How","Are","You“};
size_t    words_size=sizeof(words)/sizeof(char *);    
//  使用整个数组初始化words
list<string> words2(words,words+words_size);    

  前面我们说过,容器是存储某中类型元素的集合,所以可以定义元素是容器类型的容器。例如,可以定义vector类型的容器ivec,其元素为string类型的vector。但是注意,在指定容器元素为容器类型时,必须使用如下空格:

vector< vector<string> >    ivec;     //合法。在两个>之间有空格
vector<vector<string>>    ivec;       //错误。在两个>之间没有空格,>>会导致歧义

二.常用操作

  顺序容器内置了一些有用的操作:(1)在容器中添加元素;(2)在容器中删除元素;(3)设置容器大小;(4)(如果有的话)获取容器内的第一个和最后一个元素。

1.begin和end

  begin和end操作产生指向容器内第一个元素和最后一个元素的下一位置的迭代器。此外还有逆序迭代器(逆序迭代器从后向前遍历容器,并反转了某些相关的迭代器操作)rbegin和rend。如下:

c.begin()            返回一个迭代器,它指向容器c的第一个元素
c.end()              返回一个迭代器,它指向容器c的最后一个元素的下一个位置
c.rbegin()           返回一个逆序迭代器,它指向容器c的最后一个元素
c.rend()             返回一个逆序迭代器,它指向容器c的第一个元素的前一个位置

2.容器添加元素操作

  下表为在顺序表中添加元素的操作。注意其中的适用范围和返回类型。

c.push_back()            在容器c的尾部添加值为t的元素。返回void类型
c.push_front(t)          在容器c的前端添加值为t的元素。返回void类型。只适用于list和deque容器类型
c.insert(p,t)            在迭代器p所指向的元素前面插入值为t的新元素。返回指向新添加元素的迭代器
c.insert(p,n,t)          在迭代器p所指向的元素前面插入n个值为t的新元素。返回void类型
c.insert(p,b,e)          在迭代器p所指向的元素前面插入由迭代器b和e标记的范围内的元素。返回void类型

  其中push_front只适用于list和deque容器类型,这个操作实现在首部插入新元素的功能。

//用push_front在容器尾部依次添加0,1,2,3
list<int>    ilist;
for(size_t i=0;i!=4;++i)
    ilist.push_front(i);
//ilist内元素序列为:3,2,1,0

  需要注意的是,任何insert或push操作都可以导致迭代器失效。所以在编写循环将元素插入到vector和deque容器中时,程序必须确保迭代器在每次循环后都的到更新。

复制代码
vector<string>    ivec;
vector<string>::iterator   iter=ivec.begin();
while(cin>>word)
    iter=ivec.insert(iter,word);    //效果和push_back一样

//以下是错误的,因为此时iter已经失效
vector<string>    ivec;
vector<string>::iterator   iter=ivec.begin();
while(cin>>word)
    ivec.insert(iter,word);    //错误,经过一轮的insert后iter即失效,不能再调用
复制代码

3.容器大小的操作

  所有容器都提供以下与容器大小相关的操作。注意resize操作可能会使迭代器失效。

c.size()                返回容器c中元素的个数。返回类型为c::size_type
c.max_size()            返回容器c可以容纳的最多的元素个数.返回类型为c::size_type
c.empty()               返回标记容器大小是否为0的布尔值
c.resize(n)             调整容器c的长度大小,使其能容纳n个元素。如果n<c.size(),则删除多出来的元素
c.resize(n,t)           调整容器c的大小,使其能容纳n个元素。所有新添加的元素值为t

  在vector和deque容器上做resize操作有可能会使其所有迭代器都失效。对于所有的容器类型,如果resize操作压缩了容器,则指向已删除的元素的迭代器会失效。

4.访问容器元素的操作

  以下为访问容器元素的操作。注意·使用越界的下标,或调用空容器的front或back函数,都会导致程序出现严重的错误。

c.back()                返回容器c的最后一个元素的引用。如果c为空,则该操作未定义
c.front()               返回容器c的第一个元素的引用。如果c为空,则该操作未定义
c[n]                    返回下标为n的元素的引用。如果n<0或n>=c.size(),则该操作未定义。只适用于vector和deque容器
c.at(n)                 返回下标为n的元素的引用。如果下标越界,则该操作未定义。只适用于vector和deque容器

5.删除容器元素的操作

  以下为删除容器元素的操作。删除操作会使一些迭代器失效,需要特别注意。下表第一个操作在删除元素前,必须保证迭代器不是指向end的迭代器。

复制代码
c.erase(p)           删除迭代器p指向的元素。返回一个迭代器,它指向被删除元素后面的元素。如果p指向容器内最后一个元素,则返回的迭代器指向容器的超出末端的下一位置。
             如果p本身就是超出容器末端的下一个位置,则该函数未定义 c.erase(b,e) 删除迭代器b和e所标记的范围内所有元素。返回一个迭代器,它指向被删除元素段后面的元素。如果e本身就是指向超出容器末端的下一个位置,
则返回的迭代器也指向容器末端的下一个位置
c.clear()            删除容器c内的所有元素。返回void
c.pop_back()         删除容器c的最后一个元素。返回void。如果容器为空,则该函数未定义
c.pop_front()        删除容器c的第一个元素。妇女会void。如果容器为空,则该函数未定义。只适用于list和deque容器

6.容器的赋值与swap操作

  下表为顺序容器的赋值操作。赋值后左右两边容器相等,尽管赋值之前两个容器的大小不同,但赋值之后两个容器的长度都为右操作数的长度。

c1=c2                删除容器c1的所有元素,然后将c2的元素复制给c1。c1和c2的类型必须相同
c1.swap(c2)          交换c1和c2的内容,c1和c2的类型必须相同。其效率比把c2元素复制到c1中要高
c.assign(b,e)        重新设置c的元素:将迭代器b和e标记范围内的元素复制到c中。b和e必须不是指向c中元素的迭代器
c.assign(n,t)        将容器c重新设置为存储n个值为t的元素

转载于:https://www.cnblogs.com/xietianjiao/p/10531819.html

C++标准模板库(STL)中,顺序容器是一类重要的容器,用于管理一组对象并提供操作这些对象的方法。它们按照元素插入的顺序存储元素,可通过元素位置进行访问[^1]。 STL定义的通用容器分为顺序容器、关联式容器容器适配器三类,顺序容器属于顺序容器,是各元素之间有顺序关系的线性表,是线性结构的可序群集。每个元素有固定位置,除非进行删除或插入操作,位置和元素本身无关,而是和操作的时间和地点有关,顺序容器不会根据元素特点排序,而是直接保存元素操作时的逻辑顺序[^2]。 常见的顺序容器类型及其特点如下: - **vector**:可变大小数组,支持快速随机访问。但在尾部之外的位置插入或删除元素可能较慢[^4]。 - **deque**:双端队列,支持快速随机访问,在头尾位置插入和删除元素的速度很快[^4]。 - **list**:双向链表,只支持双向顺序访问,在任何位置进行插入或删除操作速度都很快[^4]。 - **forward_list**:单向链表,只支持单向顺序访问,在链表任何位置进行插入或删除操作速度都很快[^4]。 - **array**:固定大小数组,支持快速随机访问,但不能添加或删除元素[^4]。 - **string**:与vector相似的容器,专门用于保存字符,随机访问快,在尾部插入或删除速度快[^4]。 顺序容器还有一些操作,如 `swap` 和 `assign` 操作。`c1.swap(c2)` 可交换 `c1` 和 `c2` 中的元素,`c1` 与 `c2` 必须有相同类型,且 `swap` 通常比从 `c2` 向 `c1` 拷贝元素快得多。`assign` 操作不适用于关联容器和 `array`,`seq.assign(b, e)` 可将 `seq` 中的元素替换为迭代器 `b` 和 `e` 所表示范围中的元素,迭代器 `b` 和 `e` 不能指向 `seq` 中的元素;`seq.assign(il)` 可将 `seq` 中的元素替换为初始化列表 `il` 中的元素;`seq.assign(n, t)` 可将 `seq` 替换为 `n` 个值为 `t` 的元素[^5]。 添加元素操作会改变容器的大小,`array` 不支持这些操作,`forward_list` 有自己专有版本的 `insert` 和 `emplace`,且不支持 `push_back` 和 `emplace_back`,`vector` 和 `string` 不支持 `push_front` 和 `emplace_front` [^5]。 以下是一个简单的使用 `vector` 的代码示例: ```cpp #include <iostream> #include <vector> void print(std::vector<int>& v) { for (std::vector<int>::iterator it = v.begin(); it != v.end(); it++) { std::cout << *it << " "; } std::cout << std::endl; } int main() { std::vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } print(v1); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值