第四章:序列容器
1、序列容器:其中的元素都可有序,但未必有序。
2、C++语言本身内置了序列容器:array。
STL提供的序列容器:vector list deque,stack,queue,priority_queue. 其中stack queue只是对deque的包装,技术上称为配接器。
4.2、Vector:
1、实现的关键技术在于:对其大小的控制以及重新配置时数据移动的效率。
2、迭代器: vector支持随机存取,而普通指针天生有这些能力,因此vector提供的是 random accessiterators。
Template<calss T, calss Alloc=alloc>
Class vector
{
Public:
TypedefT value_type;
Typedef value_type* iterator;//vector的迭代器就是普通指针!!
、、、、、、
};
如定义:vector<int>::iterator it;//it的类型就是 int*!
3、vector的数据结构: 线性连续空间。 一两个迭代器 start/finnish分别指向配置的来的连续空间中目前已被使用的范围,迭代器end_of_storage指向整块连续空间(含备用)的尾端。
4、空间动态增加: 并不是在原空间之后续接新空间,而是以原空间的两倍配置一块新的空间,然后拷贝原有内容,再在其后构造新的元素,并释放原有空间。
因此,对vector的操作一旦引起空间重置,指向原vector的所有迭代器都失效了!
4.3 、list
1、好处在于 每次插入或删除一个元素,就配置或者释放一个元素空间,故list对于空间的运用绝对精准,没有浪费。
2、list的节点:list本身和list节点是不同的结构。 STL 提供的list是一个双向链表,节点有两个指针 prev、 next,一个数据成员 data。
3、list的迭代器:
List的节点不保证在连续空间,因此不能再用原始指针。List的迭代器指向其节点,多节点进行操作! STL list的迭代器是Bidirecttional iterator。
List的插入、接合(splice)都不会造成原迭代器失效。List的元素操作也只是 指向被删除元素的那个迭代器失效,其他不受影响。
5、list的数据结构:
SGIlist是环装的双向链表,因此只需要一个指针就可以完整表现整个链表。
6、list必须使用自己的sort()成员函数,不能使用STL算法的sort|(),STL的sort()只能接受RandomAccessIterator。
4.4、deque 由于需要维护假象的线性“连续空间”,因此deque的实现较vector和list复杂得多,关键在于其迭代器的实现。
1)、vector连续线性空间,deque则是双向开口的线性连续空间。
Deque可在头尾两端分别做元素的插入和删除操作。Vector虽在在技术上也可以实现头尾的插入与删除操作,但是在头部操作时效率极差!
2)、deque没有如vector那样的容量观念,它是动态的以分段连续的空间组合而成,随时可以增加一段新的空间并连接在其头端或尾端。deque也就不用提供空间保留(reserve())功能。
3)、deque也提供随机访问迭代器,但不是普通指针,比vector复杂很多,因此除非必要,应尽可能选择使用vector。
4)、对deque的排序,为了最高效率,可把其完整复制到vector,用STL sort()排序,然后在复制回deque。
5)、deque的中控器:
采用一块小的连续空间作为主控(map),其中每个元素(也称节点)都是指针,指向另一段较大的连续空间(称为缓冲区)。缓冲区才是正真的deque的存储主体。
6)、deque的迭代器: 迭代器是deuque的数据成员,迭代器中
node:一个指向map接节点的指针,以及指向该节点的指针所指的缓冲区的指针:
cur:当前list的元素位置,
first:当前缓冲区的开头,
last:当前缓冲区的结尾的下一个位置。
7)、deque除了维护一个指向map的指针外,还维护start,finish两个迭代器,分别指向第一缓冲区的一个元素,和最后一个缓冲区的最后一个元素的下一个位置。还需记住目前map的大小,一旦map所提供的节点不足,就必须重新配置一块更大的map。
8)、deque的构造与内存管理:
Deque的模板参数deque<int,alloc,10>;//其中第三个参数为指定每个缓冲区的大小,默认为512 bytes。此处指定为10),则每个缓冲区大小为4*10=40bytes。
4.5、stack::配接器(container adapter)
1、Stack是一种先进后出的数据结构,只有一个出口:允许新增元素、移除元素、取得最顶端元素。除了对顶端进行操作以外没有任何方法可以获取其他元素。即不允许有遍历操作。
2、SGI STL默认以deque为底部结构,改变其接口,形成stack.。因而satck的实现代码很简单。
3、stack的实现完全利用其底层所封装的结构deque。List也是上端开口,故可以设置底层结构为list。
4、stack不提供迭代器,也不提供遍历或者走访功能,只能对顶端进行操作。
4.6、 queue: 配接器
1、一种先进先出的数据结构。除了最底端加入元素,最顶端取出元素外,不能对任何其他任何元素存取操作。即不允许遍历操作。
2、SGI STL以deque为底层结构,封装得到queue。
3、queue只有顶端元素才有机会被外界取用。 没有迭代器,不提供遍历操作。
4、可以以list作为其底层结构。
4.7、heap:
complete binary tree:整棵binary tree除了最底层叶子节点外,是完全填满的,而叶子节点由左至右不得有空隙。
1、heap并不是一种STL容器组件,他是priority queue的底层助手。
2、bianary heap是一种completebinary tree (完全二叉树)。
3、把一complete tree 的所有节点按从上往下 从左至右的顺序放入vector中(位置0保留),则必有父节点位于i处,则左子节点位于2*i,而右子节点位于2i+1处。
4.8、 priority_queue 配接器
1、Priority_queue是一个有权值观念的queue,其内元素并非按照被推入顺序排序,而是按权值排序,权值最大者排在最前面。其他操作与queue一样。默认情况下priority_queue是用一个vector表现的complete_tree完成的。Max_heap即可满足其以权值自动排序的要求。
2、priority_queue只有顶端元素才有机会被外界取用,不提供遍历功能,不提供迭代器。
4.9 、单向链表 slist