C++容器总结1——顺序容器和顺序容器适配器

容器

容器是容纳特定类型对象的集合,容器的类型分为顺序容器,容器适配器和关联容器,顺序容器将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素。

顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。标准库定义了三种顺序容器类型:vector,list和deque。他们得差别在于访问元素的方式,以及添加或删除元素相关操作的运行代价。

适配器是根据原始容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。顺序容器适配器包括stack,queue和priority_queue类型。

标准库还定义了几种关联容器,其元素按照key排序。

标准库为容器类型定义的操作强加了公共的接口。这些容器类型的差别在于他们提供哪些操作,但如果两个容器提供了相同的操作,则他们的接口(函数名和参数个数)相同。容器类型的操作集合层次如下

1.一些操作适用于所有容器类型;

2.一些操作只适用于顺序或关联容器类型的一个子集;

3.一些操作只适用于顺序或关联容器类型类型的一个子集;

顺序容器

顺序容器的初始化以及定义

使用顺序容器首先要包含头文件:

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

顺序容器的定义

vector<int> vec;//所有容器是模板
list<int> lis;//<>中提供容器中存放的元素的类型,可以是常用数据类型也可以是自己定义的类类型</span>
deque<int> items;//容器类型都定义了默认构造函数用于创建指定类型的空容器对象,默认构造函数不带参数

顺序容器的初始化

vector<int> vec;//定义包含int型元素的容器
vector<int> vec1(10);//包含10个int型元素的容器
vector<int> vec2(10,1);//包含10个int型元素的容器每个被初始化为1,只适用于顺序容器
vector<int> vec3(vec2);//将vec2中的元素复制到vec3,只适用于顺序容器

不能直接将一种容器中的元素赋值给另一种容器,但是可以使用传递一对迭代器间接实现该功能

vector<string> svec;
list<string> ilist(svec);//容器不同,不能复制
list<string>slist(svec.begin(),svec.end());//使用迭代器,不要求容器类型相同

注:除引用类型外,所有内置或复合类型(包括容器类型本身)都可以用做元素类型,IO库类型不能够作为容器类型;

当使用类类型作为元素类型,如果指定了容器的大小,则必须提供单个初始化式的构造函数。

vector< <vector<string> >lines;

顺序容器的操作

顺序容器的类型别名

begin和end成员

所有容器都提供begin和end操作符,用于返回迭代器,begin返回迭代器指向的第一个元素,end返回迭代器指向的容器末端的元素下一个,它指向一个不存在的元素,当容器为空,两个操作符返回的值相等。

容器中添加元素

容器支持以下操作添加新元素:

任何insert和push操作可能导致迭代器失效,当编写程序时,程序必须确保迭代器在每次插入操作后更新。要避存储end操作返回的迭代器。

关系操作符

所有容器都支持关系操作符来比较容器中的元素,比较时,容器类型,容器中元素的类型都必须相同。容器比较是基于容器内元素的比较,即其内部元素类型定义的比较操作。如果容器的元素类型不支持某种操作符,则该容器不能做比较运算。

容器大小操作

访问元素

删除元素

赋值和swap

使用赋值操作符时,赋值前两容器长度可以不相等,但赋值后两容器都具有右操作数的长度。

=和assign会使左操作数容器的所有迭代器失效,swap不会。

assign可以实现类型不同但相互兼容的元素的赋值。

swap实现交换两个容器内所有元素的功能,要交换的容器类型必须匹配,操作数必须是相同类型的容器,而且所存储的元素类型也必须相同。

capacity和reserve

由于vector元素以连续方式存放,当添加了新元素,但是容器中已经没有容纳新元素的空间,就回重新分配内存空间,将就空间的存储的元素复制进去,接着插入 新元素,最后撤销旧的存储空间。为了使vector实现快速内存分配,其实际分配的容量要比当前所需的空间多一些。

vector提供两个成员函数capacity和reserve来与容器的内存分配实现交互。

capacity操作获取在容器需要分配更多存储空间之前能够存储的元素总数,通常比size要大。

reserve操作告诉容器应该预留多少个元素的存储空间。

容器适配器

适配器是使一个事物的行为类似于另一个事物的行为的一种机制,适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。如:stack可使任何一种顺序容器以栈的方式实现。

使用适配器必须包含头文件

#include<stack>
#include<queue>

容器适配器的通用操作和类型

适配器的初始化

所有适配器都有两个构造函数1.默认构造函数:常见空对象2.带一个容器参数的构造函数:将参数容器的副本作为基础值

deque<int>deq;
stack<int>stk(deq);

覆盖基础容器类型

默认的stack和queue都是基于deque容器实现,而priority_queue则在vector容器上实现。

如果要覆盖其关联的容器类型,可通过将一个顺序容器指定为适配器的第二个类型实参:

stack< string,vector<string> >str_stk;

对于给定的适配器,关联的容器必须满足一定的约束条件

stack可以关联所有的顺序容器;

queue要求关联的容器支持push_front,因此只能建立在list和deque上;

priority_queue要求提供随机访问功能,因此只建立在vector和deque上;

栈适配器

栈的操作如下:

所有的容器适配器都依据其基础容器类型所支持的操作来定义自己的操作,比如,stack建立在deque容器上,因此采用deque提供的操作来实现栈功能。

队列和优先队列

priority_queue允许用户为队列中存储的元素设置优先级,这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。

迭代器和迭代器操作

迭代器是一种检查容器内部元素并且遍历元素的数据类型,标准库为每一种标准容器定义了一种迭代器类型,如vector迭代器:

vector<int>::iterator iter

所有迭代器都具有相同的接口,例如迭代器可使用解引用操作符(*操作符)来访问迭代器所指向的元素

*iter=0//将iter指向的值设为0.

下表迭代器为所有标准库容器类型所提供的运算

deque和vector还提供了额外的操作符

vector和deque这两种容器为其元素提供快速随机访问,而list只支持自增自减以及相等不等运算。

const_iterator

该类型只能用于读取容器内元素但不能改变其值。

各种容器的比较

vector:提供元素的随机访问,除容器尾部外,在容器任何其他位置上插入(或删除)操作都要求移动被插入(或删除)元素右边的所有元素。

list:表示不连续的内存区域,可高效的在任何位置插入和删除一个元素,但是不支持随机访问

deque:在deque队列的两端插入和删除元素非常快,同时deque具有以下性质:1.在容器中间插入或删除效率比较低;2.可高效地在其首部实现插入和删 除,就像在容器尾部 一样;3.支持对所有元素的随机访问;4.在容器首部或尾部插入元素不会使任何迭代器失效,而在首部或者尾部删除则会使指向被删除元素的迭代器时效,在任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器都失效。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 23:47:59

C++容器总结1——顺序容器和顺序容器适配器的相关文章

C++ - 复制容器(container)的元素至另一个容器

复制容器(container)的元素至另一个容器 本文地址: http://blog.csdn.net/caroline_wendy C++复制容器(container)元素, 可以使用标准库(STL)的copy()和copy_n()函数. 函数样式: OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) 代码: /* * main.cpp * * Created on: 2014

在 overlay 中运行容器 - 每天5分钟玩转 Docker 容器技术(51)

上一节我们创建了 overlay 网络 ov_net1,今天将运行一个 busybox 容器并连接到 ov_net1: 查看容器的网络配置: bbox1 有两个网络接口 eth0 和 eth1.eth0 IP 为 10.0.0.2,连接的是 overlay 网络 ov_net1.eth1 IP 172.17.0.2,容器的默认路由是走 eth1,eth1 是哪儿来的呢? 其实,docker 会创建一个 bridge 网络 "docker_gwbridge",为所有连接到 overlay

容器生态系统 - 每天5分钟玩转容器技术(2)

对于像容器这类平台级别的技术,通常涉及的知识范围会很广,相关的软件,解决方案也会很多,初学者往往容易迷失. 那怎么办呢? 我们可以从生活经验中寻找答案.当我们去陌生城市旅游想了解一下这个城市一般我们会怎么做? 我想大部分人应该会打开手机看一下这个城市的地图: 城市大概的位置和地理形状是什么? 都由哪几个区或县组成? 主要的交通干道是哪几条? 同样的道理,学习容器技术我们可以先从天上鸟瞰一下: 容器生态系统包含哪些不同层次的技术? 不同技术之间是什么关系? 哪些是核心技术哪些是辅助技术? 首先得对

从头认识java-13.11 对比数组与泛型容器,观察类型擦除给泛型容器带来什么问题?

这一章节我们继续类型擦除的话题,我们将通过对比数组与泛型容器,观察类型擦除给泛型容器带来什么问题? 1.数组 package com.ray.ch13; public class Test { public static void main(String[] args) { Fruit[] fruits = new Apple[5]; fruits[0] = new Apple(); fruits[1] = new Fuji(); fruits[2] = new Fruit(); } } cla

【转】Unity3D中脚本的执行顺序和编译顺序

支持原文,原文请戳: Unity3D中脚本的执行顺序和编译顺序 在Unity中可以同时创建很多脚本,并且可以分别绑定到不同的游戏对象上,它们各自都在自己的生命周期中运行.与脚本有关的也就是编译和执行啦,本文就来研究一下Unity中脚本的编译和执行顺序的问题. 事件函数的执行顺序 先说一下执行顺序吧. 官方给出的脚本中事件函数的执行顺序如下图:  我们可以做一个小实验来测试一下: 在Hierarchy视图中创建三个游戏对象,在Project视图中创建三条脚本,如下图所示,然后按照顺序将脚本绑定到对

从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?

这一章节我们继续类型擦除的话题,我们将通过对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题? 1.数组 package com.ray.ch13; public class Test { public static void main(String[] args) { Fruit[] fruits = new Apple[5]; fruits[0] = new Apple(); fruits[1] = new Fuji(); fruits[2] = new Fruit(); } } cla

品尝阿里云容器服务:用nginx镜像创建容器,体验基于域名的路由机制

在前一篇博文中我们了解了阿里云容器服务的路由机制: 请求 -> 负载均衡80端口 -> 容器主机9080端口 -> acsrouting路由容器80端口 --基于域名--> Web站点容器端口 在这篇博文中,我们用nginx镜像创建一个容器实际体验一下. 使用容器服务首先要创建一个集群(Cluster),比如这里我们创建一个名叫websites的集群(使用的是swarm mode): 创建好集群后,点击“管理”,进入集群管理页面 -> “负载均衡” -> “域名设置”,

SQL优化之count,表的连接顺序、条件顺序,in和exist

一.关于count 看过一些关于count(*)和count(列)的文章,count(列)的效率一定比count(*)高吗? 其实个人觉得count(*)和count(列)根本就没有可比性,count(*)统计的是表里面的总条数,而count(列)统计的是当列的非空记录条数. 不过我们可以通过实验来比较一下: 首先创建测试表: drop table test purge; create table test as select * from dba_objects; update test  s

【安卓】乾坤大罗移,将容器触摸事件传至另一容器、!

思路: 1.基于view.dispatchTouchEvent 作用: 1.点击时,透过容器点到不是其子控件的控件.! 2.透过透明activity或dialog,将事件传至下方的activity.! 注:1>还可通过MotionEvent.obtain(downTime, eventTime, action, x, y, metaState);模拟事件,如用于引导中.! 被点击的容器: public class MyLinearLayout extends LinearLayout { pub

css样式加载顺序及覆盖顺序深入理解

注:内容转载 很多的新手朋友们对css样式加载顺序和覆盖顺序的理解有所偏差,下面用示例为大家详细的介绍下,感兴趣的朋友不要错过 { height: 100%; width: 200; position: absolute; left: 0; border: solid 2 #EEE; } .current_block { border: solid 2 #AE0; } 查找一些教材中(w3schools等),只说css的顺序是"元素上的style" > "文件头上的st