第四章 序列式容器
总体概述如下:
vector实现的底层实现对象是数组,list底层实现对象是双向循环列表,deque是双端开头的连续线性空间(实现起来比较麻烦);stack和queue是配接器,底层可以有list、deque(queued的默认实现是deque)来实现。
1. vector
vector是动态空间,维护的是一个连续的线性空间,实现动态增长的机制如下:1.配置新空间;2.数据移动;3.释放旧空间
SGI的STL的空间配置策略是:以原来大小的两倍另外配置一块较大的空间
vector的迭代器就是普通指针;
template <class T, class Alloc = alloc>
class vector{
public :
typedef T value_type;
typedef value_type* iterator;
};
Vector的数据结构:
template <class T, class Alloc = alloc>
class vector{
……
protected :
iterator start;
iterator finish;
iterator end_of_storage;
……
};
迭代器start和finish分别指向配置的的来的连续空间中已经被使用的范围,end_of_storage指向整块连续空间的尾端;
2 list
从list的节点定义如下:
template <class T>
struct _list_node{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
我们可以看出,list实际上是一个双端队列;
STL中节点的插入、删除都与数据结构课程中的链表操作无异,不在详述;
2. deque
deque是一个双端开口的队列,头尾都可以做pop()/push操作;
deque与vector的最大差异,一在于deque允许在O(1)时间内对头端进行元素的插入和移除,二在于deque没有容量(capacity)的概念;
deque的数据结构:
deque是一段一段定量连续的空间构成,一旦有必要在deque两端申请新空间,便申请一段定量的连续空间,串接在整个deque的首端或尾端,具体实现是有一个中控器、若干迭代器、若干缓冲区buffer构成,如下:
与vector非常不一样。
Map实际上就是一个是整数组,里面的每一个元素都指向缓冲区的开头。每一个迭代器的数据结构定义如下:
T data;
T* cur;
T* finish;
T* last;
map_pointer node;
显然,iterator在移动的时候,要比较注意:各种指针运算,加、减、前进、后退,都不能直观视之;其中最关键的就是:一旦遇到缓冲区的边缘,要特别当心,可能要调到先一个缓冲区,也有可能要新开辟一个缓冲区;
迭代器在随机访问的时候(前进或者后退N个单元,也要注意这种情况的发生)
3. heap
heap实现了优先级队列priority_queue。他的实现与任何一本数据结构的教材无区别,用的是最大堆。(主要是堆调整、建堆两个步骤,对于堆这个数据结构,我还是非常熟悉的,呵呵)。