STL源码剖析: 第4章 序列式容器

4.1 容器的概观与分类

title

4.2 vector

4.2.1 迭代器

vector的迭代器只是一个指针,因为空间连续,所有的++,–操作都有了,不需要新建类型来重载
title

4.3 list

双向链表

4.3.1 迭代器

list空间不连续,没法直接进行指针的++,–来达到前一个后一个元素,所以必须设计iterator类,重载++,–,以及operator*(),统一成类指针形式
title

4.3.2 关键函数解析

在position处连续插入n个值为x的对象
insert(position, n, x)

title
title
title

4.4 deque

4.4.1 迭代器

主要精髓是用了迭代器来做一层封装,迭代器重载了++,–等运算符
1) 在外层看来,用迭代器进行++就能遍历整个deque空间
2) 在内部实现,用了两个迭代器,start 和 finish,
真正的元素数据就存放在[start.cur,finish.cur)之间

其中,每个迭代器维护了4个指针, cur, first, last, node
其中

指针含义
cur指向实际的数据内存位置
[first,last)只是用来指示空间范围,在cur超过这个范围的时候,需要切换到上一个或者下一个node所指向的那边缓存区
node指向了map,类型为T**,*node表示元素数据缓存区的起始地址,node本身在map段里是连续的,可以直接++,–

这样在用户写程序的时候,构造一个迭代器,在迭代器start和finish范围内遍历,实际上就是利用构造的迭代器的cur指针,在[start.cur, finish.cur),这样就能遍历所有deque空间的元素,用户看起来像是和用vector一样一段连续的空间;

这种遍历,通过对迭代器类重载==, !=来实现,比较迭代器的cur指针是否相同,比如判断是否超出最后一个元素,可以判断user_ite.cur == finish.cur,如果相等则表示确实到达了最后一个元素的下一个元素位置。

title

4.4.2 内存分布与扩展

4.4.2.1 creat_map_and_nodes

creat_map_and_nodes(size_type num_elements)
参数解析,num_elements表示deque要保存的元素个数

其中node在map居中放置,两端预留空间,如上图map所示,黑节点居中放置
title

4.4.2.2 reserve_map_at_back

判断map空间是否不足,不足的话换一张新的map,将原来的map里的内容复制到新map的居中位置,同样保留两端的预留空间,然后重新设置迭代器first,和finish,使之和新map对应

  iterator _M_reserve_elements_at_back(size_type __n) {
    size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1;
    if (__n > __vacancies)
      _M_new_elements_at_back(__n - __vacancies);
    return _M_finish + difference_type(__n);
  }
4.4.2.3 reallocate_map

reserve_map_at_back内部判断出后端的map备用空间不够用时,会调用reallocate_map函数
后端map备用空间满足不了用户要求的nodes_to_add个预留空间的需求,但是map还是可能能容纳增加了预留个数的node节点,因为左边可能很空,整体变得很偏右侧,只要调整居中即可,这就是if的由来
title

4.4.3 insert

其实就是多增加一个元素,然后用前移或者后移覆盖,然后再对指定位置处的元素赋值
title
title

4.5 stack

不作为一个容器,而作为一个配接器,本身没有迭代器

4.6 queue

不作为一个容器,而作为一个配接器,本身没有迭代器
title

4.7 heap

不作为一个容器,只是作为算法,这样隐式的存在,需要配合vector使用
floyd建堆:
总体思想,通过一个节点将两个现有堆进行合并,合成为一个堆
通过根节点连接两个堆,然后对根节点进行下滤调整,使堆合法
实际上,需要从最后一个节点的父节点开始,从后往前,将左右子堆合并,直到根节点,这样,其合并的复杂度为堆中各节点的高度之和,效率为 O(n) ,邓俊辉《数据结构》书上有详解

template <class _RandomAccessIterator, class _Tp, class _Distance>
void 
__make_heap(_RandomAccessIterator __first,
            _RandomAccessIterator __last, _Tp*, _Distance*)
{
  if (__last - __first < 2) return;
  _Distance __len = __last - __first;
  _Distance __parent = (__len - 2)/2;   //找最后一个节点的父节点

  while (true) {
    __adjust_heap(__first, __parent, __len, _Tp(*(__first + __parent)));
    if (__parent == 0) return;
    __parent--;
  }
}

4.8 priority_queue

跟heap差不多,主要增加了可以选择构造大顶堆还是小顶堆

4.9 slist

4.9.1 slist特点

不是STL的标准
单向链表,只能从前往后走
title

4.9.2 slist迭代器架构

title

4.9.3 slist end()

end()返回的迭代器永远指向0
title
title

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值