STL容器类型

来源:互联网 发布:网络晒娃 编辑:程序博客网 时间:2024/06/05 16:46

容器

所谓STL容器,即是将最常运用的一些数据结构(data structures)实现出来。

容器是指容纳特定类型对象的集合。根据数据在容器中排列的特性,容器可概分为序列式(sequence)和关联式(associative)两种。

迭代器是一种检查容器内元素并遍历元素的数据类型。它提供类似指针的功能,对容器的内容进行走访。

#include<iterator>例如:std::vector<int> IntVector;std::vector<int>::iterator first=IntVector.begin();// begin()得到指向vector开头的Iterator,*first得到开头一个元素的值std::vector<int>::iterator last=IntVector.end();// end()得到指向vector结尾的Iterator,*last得到最后一个元素的值

一、序列式容器

所谓序列式容器,其中的元素都可序(ordered),但未必有序(sorted)。数组为C++语言内置的序列容器,STL另外提供vector、list、deque(double-ended queue)。它们的差别在于访问元素的方式,以及添加或删除元素相关操作的运行代价。

标准库还提供了三种容器适配器(adapter),所谓适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。顺序容器适配器包括stack、queue、priority_queue等序列式容器。其中stack和queue由于只是将deque改头换面而成,技术上被归类为一种配接器(adapter),priority_queue是有优先级管理的队列。

1、 vector

向量 ,相当于一个数组

在内存中分配一块连续的内存空间进行存储。支持不指定vector大小的存储。STL内部实现时,首先分配一个非常大的内存空间预备进行存储,即capacituy()函数返回的大小,当超过此分配的空间时再整体重新放分配一块内存存储,这给人以vector可以不指定vector即一个连续内存的大小的感觉。通常此默认的内存分配能完成大部分情况下的存储。
优点:

(1) 不指定一块内存大小的数组的连续存储,即可以像数组一样操作,但可以对此数组进行动态操作。通常体现在push_back()pop_back()(2) 随机访问方便,即支持[ ]操作符和vector.at()(3) 节省空间。

缺点:

(1) 在内部进行插入删除操作效率低。(2) 只能在vector的最后进行pushpop,不能在vector的头进行pushpop。(3) 当动态添加的数据超过vector默认分配的大小时要进行整体的重新分配、拷贝与释放

常用:

assign(first,last):用迭代器first,last所指定的元素取代向量元素assign(num,val):用valnum份副本取代向量元素at(n):等价于[]运算符,返回向量中位置n的元素,因其有越界检查,故比[]索引访问安全front():返回向量中第一个元素的引用back():返回向量中最后一个元素的引用begin():返回向量中第一个元素的迭代器end():返回向量中最后一个元素的下一个迭代器(仅作结束游标,不可解引用)max_size():返回向量类型的最大容量(2^30-1=0x3FFFFFFFcapacity():返回向量当前开辟的空间大小(<= max_size,与向量的动态内存分配策略相关)size():返回向量中现有元素的个数(<=capacityclear():删除向量中所有元素empty():如果向量为空,返回真erase(start,end):删除迭代器start end所指定范围内的元素erase(i):删除迭代器i所指向的元素erase()返回指向删除的最后一个元素的下一位置的迭代器insert(i,x);把x插入到迭代器i所指定的位置之前insert(i,n,x):把xn份副本插入到迭代器i所指定的位置之前insert(i,start,end):把迭代器startend所指定的范围内的值插入到迭代器i所指定的位置之前push_back(x):把x推入(插入)到向量的尾部pop_back():弹出(删除)向量最后一个元素rbegin():返回一个反向迭代器,该迭代器指向的元素越过了向量中的最后一个元素rend():返回一个反向迭代器,该迭代器指向向量中第一个元素reverse():反转元素顺序resize(n,x):把向量的大小改为n,新元素的初值赋为xswap(vectorref):交换2个向量的内容

2、list

双向链表

每一个结点都包括一个信息块Info、一个前驱指针Pre、一个后驱指针Post。可以不分配必须的内存大小方便的进行添加和删除操作。使用的是非连续的内存空间进行存储。
优点:

(1) 不使用连续内存完成动态操作。(2) 在内部方便的进行插入和删除操作(3) 可在两端进行pushpop

缺点:

(1) 不能进行内部的随机访问,即不支持[ ]操作符和vector.at()(2) 相对于vector占用内存多

常用:

以下未列出与vector相同的通用操作。push_front(x):把元素x推入(插入)到链表头部pop_front():弹出(删除)链表首元素merge(listref):把listref所引用的链表中的所有元素插入到链表中,可指定合并规则splice():把lst连接到pos的位置remove(val):删除链表中所有值为val的元素remove_if(pred):删除链表中谓词pred为真的元素(谓词即为元素存储和检索的描述,如std::less<>std::greater<>那么就按降序/升序排列,你也可以定义自己的谓词)sort():根据默认的谓词对链表排序sort(pred):根据给定的谓词对链表排序unique():删除链表中所有重复的元素unique(pred):根据谓词pred删除所有重复的元素,使链表中没有重复元素注意:vector和deque支持随机访问,而list不支持随机访问,因此不支持[]访问!

list没有空间预留习惯,所以每分配一个元素都会从内存中分配,每删除一个元素都会释放它占用的内存。list在哪里添加删除元素性能都很高,不需要移动内存,当然也不需要对每个元素都进行构造与析构了,所以常用来做随机操作容器。与vector不同是,当向容器中插入或删除元素后,链表迭代器指向元素将不变。 如果一个vector有5个元素,中间插入一个,那么第五个元素包含的值将是以前第四个元素的值,因此,迭代器指向的位置不变,但是数据不同。然而,在链表中插入新元素并不会移动已有的元素,而只是修改链接信息。 指向某个元素的迭代器仍然指向该元素,也就是值相同,链接的位置不同了

3、deque

双端队列 double-end queue

deque是在功能上合并了vector和list,看起来像是list和vector的结合品。
优点:

(1) 随机访问方便,即支持[ ]操作符和vector.at()(2) 在内部方便的进行插入和删除操作(3) 可在两端进行pushpop

缺点:

(1) 占用内存多

常用:

Operators:[]用来访问双向队列中单个的元素front():返回第一个元素的引用push_front(x):把元素x推入(插入)到双向队列的头部pop_front():弹出(删除)双向队列的第一个元素back():返回最后一个元素的引用push_back(x):把元素x推入(插入)到双向队列的尾部

在标准库中vector和deque提供几乎相同的接口,在结构上它们的区别主要在于这两种容器在组织内存上不一样,deque是按页或块来分配存储器 的,每页包含固定数目的元素,相反vector分配一段连续的内存,vector只是在序列的尾段插入元素时才有效率,而deque的分页组织方式即使在容器的前端也可以提供常数时间的insert和erase操作,而且在体积增长方面也比vector更具有效率。deque在开始和最后添加元素都一样快,并提供了随机访问方法,像vector一样使用[]访问任意元素,但是随机访问速度比不上vector快,因为它要内部处理堆跳转。

使用区别:

1 、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector 2 、如果你需要大量的插入和删除,而不关心随即存取,则应使用list 3 、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque

4、基于deque的顺序容器适配器stack、queue(priority_queue)

(1)stack

stack是一种后进先出(First In Last Out,FILO)的数据结构,它只有一个出口。stack允许新增元素、移除元素、取得最顶端元素。但除了最顶端外,没有任何其他方法可以存取stack的其他元素,换言之,stack不允许随机访问。

STL以deque作为stack的底层结构,对deque封闭期头端开口,稍作修改便形成了stack。

将元素插入stack的操作称为push,将元素弹出stack的操作称为pop。stack所有元素的进出都必须符合“后进先出”的条件,只有stack顶端的元素,才有机会被外界取用。stack不提供走访功能,也不提供迭代器。

(2)queue

queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。

queue允许新增元素、移除元素、从最底端加入元素、取得最顶端元素。但除了最底端可以加入、最顶端可以取出,没有任何其他方法可以存取queue的其他元素。换言之,queue不支持随机访问。

STL以deque作为queue的底层结构,对deque封闭其底端的出口和前端的入口,稍作修改便形成了queue。

(3)priority_queue

priority_queue为优先级队列,它允许用户为队列中存储的元素设置优先级。这种队列不是直接将新元素放置在队列尾部,而是放置在比它优先级低的元素前面,即提供了一种插队策略。标准库默认使用<操作符来确定他们之间的优先级关系。即权重大的排在队首。

使用priority_queue时,包含文件。

二、关联式容器

所谓关联式容器,概念上类似关联式数据库(实际上则简单许多):每项数据(元素)包含一个键值(key)和一个实值(value)。当元素被插入到关联式容器中时,容器内部数据结构(可能是RB-tree,也可能是hash-table)便依照其键值大小,以某种特定规则将这个元素放置于适当位置。关联式容器没有所谓头尾(只有最大元素和最小元素),所以不会有push_back(),push_front(),pop_back(),pop_front(),begin(),end()这样的操作。

一般而言,关联式容器的内部结构是一个balanced binary tree(平衡二叉树),以便获得良好的搜索效率。balanced binary tree有很多种类型,包括AVL-tree、RB-tree、AA-tree,其中广泛运用于STL的是RB-tree(红黑树)。

标准的STL关联式容器分为set(集合)和map(映射类)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表)。这些容器的底层机制均以RB-tree完成(红黑树)。RB-tree也是一个独立容器,但并不开放给外界使用。

此外,SGI STL还提供了一个不在标准规格之列的关联式容器:
hash table(散列表,哈希表),以及以此 hash table 为底层机制而完成的hash_set(散列集合)、hash_map(散列映射表)、hash_multiset(散列多键集合)、hash_multimap(散列多键映射表)。

关联容器的长处在于,它提供了对元素的快速访问。 与序列相似,联合容器也允许插入新元素,不过不能指定元素的插入位置。原因是联合容器通常包含用于确定数据存放位置的算法,以便能够很快检索信息。

1、map、 multimap

两者值的类型与关键字不同。 map关键字唯一,multimap关键字不唯一。

关联式容器std::map成员函数

#include<map>map建立key-value映射std::map<key, value> mp;std::map<key, value, comp> mp;key为键值value为映射值comp可选,为键值对存放策略,例如可为std::less<>,键值映射对将按键值从小到大存储其成员函数如下:count():返回map中键值等于key的元素的个数equal_range():函数返回两个迭代器——一个指向第一个键值为key的元素,另一个指向最后一个键值为key的元素erase(i):删除迭代器所指位置的元素(键值对)lower_bound():返回一个迭代器,指向map中键值>=key的第一个元素upper_bound():函数返回一个迭代器,指向map中键值>key的第一个元素find(key):返回键值为key的键值对迭代器,如果没有该映射则返回结束游标end()注意map的[]操作符,当试图对于不存在的key进行引用时,将新建键值对,值为空。

2、set、multiset

在set头文件中(以前分别为set.h和multiset.h);

两者值的类型与关键字相同。 set删除相同的元素,multiset不会。

http://blog.csdn.net/phunxm/article/details/5081472
http://blog.csdn.net/heyutao007/article/details/6905589

0 0