Array,Vector,List,Deque的区别与联系【转+改】
数组
内存连续分配,长度大小固定,内置的最基础的数据结构之一。支持随机访问和随机存储。
该类型数据所占内存空间最小。
Vector
是C++ STL中的一个容器。和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随机存取(即使用[]操作符访问其中的元素),但由于它的内存空间是连续的,所以在中间进行插入和删除会造成内存块的拷贝(复杂度是O(n)),另外,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。
Vector的原型定义如下。可以看到,作为一个容器,相比array附加了很多数据成员,因而从整体上而言,其内存空间占用较数组更多。但是仅仅就分配的连续的数组空间而言,和内置型数组占用空间大小基本一致。
// vector 基类 _Vector_base 定义
template <class _Tp, class _Alloc>
class _Vector_base {
public:
typedef _Alloc allocator_type;
// 获取一个空间配置器对象
allocator_type get_allocator() const { return allocator_type(); }
// 默认构造:没有指定初始节点个数
_Vector_base(const _Alloc&)
: _M_start(), _M_finish(), _M_end_of_storage() {}
// 构造函数:指定节点个数n
_Vector_base(size_t __n, const _Alloc&)
: _M_start(), _M_finish(), _M_end_of_storage()
{
// 分配 n 个节点所需空间
_M_start = _M_allocate(__n); // _M_start 指向起始位置
_M_finish = _M_start; // _M_finish 指向其实位置
_M_end_of_storage = _M_start + __n; // _M_end_of_storage指向内存末尾节点
}
// 析构函数:释放内存空间
~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } protected:
_Tp* _M_start; // 指向第一个元素所在的节点
_Tp* _M_finish; // 指向最后一个元素所在节点的下一个节点
_Tp* _M_end_of_storage; // 可用内存空间的末尾节点
// 空间配置器
typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;
// 分配 n 个节点所需要的空间
_Tp* _M_allocate(size_t __n)
{ return _M_data_allocator::allocate(__n); }
// 释放 n 个节点所对应的空间
void _M_deallocate(_Tp* __p, size_t __n)
{ _M_data_allocator::deallocate(__p, __n); }
};
List
list是由数据结构中的双向链表实现的,因此它的内存空间可以是不连续的。因此只能通过指针来进行数据的访问,这个特点使得它的随机存取变的非常没有效率,需要遍历中间的元素,搜索复杂度O(n),因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入。
其定义如下所示,很明显,除了数据域以外,还包含前向指针后后序指针,因而其耗费的空间比vector要大。
// ListNodeBase定义
struct _List_node_base {
_List_node_base* _M_next;
_List_node_base* _M_prev;
}; // ListNode定义
template <class _Tp>
struct _List_node : public _List_node_base {
_Tp _M_data; // 数据域
};
Deque
deque是双端队列,在队列头部和尾部可以快速的进行元素的插入和删除操作,相比vector而言有一定的优势,同时由于内部构造的设计,不存在vector那样扩充时带来的“配置新空间 / 移动旧数据 / 释放旧空间”问题。deque还提供Random Access Iterator,可以随机访问容器内的元素。deque同时还是STL中queue和stack的底层依赖组件。
下面的图片展示deque的内部结构设计。可以看到,deque拥有一个bitmap结构(称之为map),map中每一个元素指向一块连续的内存块,后者才是真正存储deque元素的地方,因为每个块都是固定大小的,但是每个块之间不要求是连续的,所以扩充空间的时候,就没有vector那样的副作用了。

deque的数据结构更为复杂,还包含了map节点,但是相比list每个节点均需要额外指针而言,其内存占用量还是较少。所以deque数据部分消耗的内存空间大小应该在vector和list之间。
需要说明的是,stack和queue的内部实现均基于deque实现,queue只能头删尾进,stack只能尾删尾进,这都是deque所支持的操作的特殊情况,或者说一个子集。
Array,Vector,List,Deque的区别与联系【转+改】的更多相关文章
- vector与deque的区别
最重要的区别,是内部实现上.deque是分段存储的. 都是支持随机存取. http://www.cnblogs.com/zhuyf87/archive/2012/12/09/2809896.html ...
- C++ vector,list,deque区别(转)
在写C++程序的时候会发现STL是一个不错的东西,减少了代码量,使代码的复用率大大提高,减轻了程序猿的负担.还有一个就是容器,你会发现要是自己写一个链表.队列,或者是数组的时候,既要花时间还要操心 ...
- C++ vector、list和deque的区别 (整理)
1.vector数据结构 vector和数组类似,拥有一段连续的内存空间,并且起始地址不变.因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内 ...
- 【转】java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别
原文网址:http://www.360doc.com/content/15/0427/22/1709014_466468021.shtml java 容器类使用 Collection,Map,Hash ...
- 一道java笔试题目:Vector和ArrayList的区别
Vector和ArrayList的区别 线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构这些类均在java.util包中本文试图通过 ...
- C++进阶 STL(1) 第一天 [容器,算法,迭代器] string容器 vector容器 deque容器
课程大纲 02实现基本原理 容器,算法,迭代器 教室:容器 人:元素 教室对于楼:容器 序列式容器: 容器元素在容器中的位置是由进入容器的时间和地点来决定 序列式容器 关联式容器: 教室中 按年龄排座 ...
- OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别
OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...
- C++ vector和list的区别
1.vector数据结构vector和数组类似,拥有一段连续的内存空间,并且起始地址不变.因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时,会造成内存 ...
- C++ 顺序容器 vector list deque 之比较
在C++标准库中定义了三种顺序容器类型:vector,list和deque.所谓顺序容器就是根据位置来存储和访问元素,元素的排列次序与元素的值无关,而是由元素添加到容器的次序决定的. vector的底 ...
随机推荐
- 【hdoj_1009】FatMouse's Trade
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1009< 本题用到贪心策略和结构体排序. 问题简化:现有资本M,N个房间,第i个房间对应着价格为F[i ...
- go语言方法实例
方便和函数的区别: 方法能给用户定义的类型添加新的行为.方法实际上也是函数,只是在声明时,在关键字func 和方法名之间增加了一个参数. package main import ( "fmt ...
- portainer,用于管理docker swarm,好像也不错哟
shipyard的模式,好像在docker 1.12之后,没有啥用武之地了,也没有更新. 接下来,集群管理和调度,最有知名度的就是rancher了. 在rancher之前,我们试一下portainer ...
- mysql:把DB1中A表a字段替换为DB2中B表b字段
UPDATE DB1.A SET a = ( SELECT b FROM DB2.B WHERE B.Id = A.id) 实例: UPDATE wordpress.`wp_posts` SET po ...
- opencv图像的旋转
#include"stdafx.h"#include"opencv2/opencv.hpp" using namespace cv;// clockwise 为 ...
- HDU 1251 统计难题 (字典树)(查询是否为前缀)
统计难题 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submi ...
- OC语言基础之NSDictionary
1.NSDictionary字典的创建 1: // key value 2: // key -==> value 3: NSDictionary *dict = [NSDictionary di ...
- IOS之Block的应用-textFeild的回调应用
Block的一点优点为可以省略回调函数,简化代码今天我就应用了以下. 以下是代码片段. _testTextField1=[[MyTextField alloc] init]; [self.view a ...
- linux+iptables搭建网关服务器
公司购买的一批云服务器只带内网,配置了一个负载均衡器(lb),这批服务器通过lb可以对外提供服务,但是这批服务器不能主动连接外网,例如使用wget下载文件,或者curl访问ttlsa.com站点. 额 ...
- PHP将字符串首字母大小写转换
每个单词的首字母转换为大写:ucwords() <?php $foo = 'hello world!'; $foo = ucwords($foo); // Hello World! $bar = ...