C++ STL标准库与泛型编程(四)Deque、Queue、Stack 深度探索

一、Deque 深度探索

双向扩充队列

push_front()           pop_front()               push_back()             pop_back()

内存中是分段连续的buffer,每次扩充时,扩充一个固定的 buffer 大小。

deque 本身大小为40个字节=2个 iterator (16) + 一个指针 (4) + 一个整数(4)         内部放做少元素是动态分配获得的,和对象本身没有关系。

模板参数中的 BufSiz 是指每个 buffer 容纳的元素个数,可自定。默认为0时,根据 sz[ sizeof(value_type) ] 的大小,

if sz < 512 则 buffersize = 512 / sz                           else  buffersize = 1

控制中心 map 是一个指针 指向一个指针的数组 vector  ,其扩充时也是两倍成长,每次扩充后 copy 原有元素到新内存的中段,时前部和后部后空出,以便于增加 map 中 node 时的操作。

template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
    typedef random_acess_iterator_tag iterator_category;
    typedef T value_type;
    typedef Ptr pointer;
    typedef Ref reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef T** map_pointer;
    typedef __dequr_iterator self;

    T* cur;
    T* first;
    T* last;
    map_pointer node;       //指向map中的元素,即是一个指向指针的指针
....
};

在队列前后入队出队时,迭代器指向边界时,会自动修正++与--所指向的地址,有能力跳到下一个缓冲区,以保证表面上看是连续的

扫描二维码关注公众号,回复: 5434955 查看本文章

在指定位置安插一个值为 x 的元素 insert(),会智能判断所安插的位置离前端还是后端比较近,从而选择效率高的一端推移,空出一个位置来放入新元素。

没有 sort() 类方法,直接使用 ::sort() STL模板函数。

  • Deque 如何模拟连续空间 — 由 deque iterator 实现

主要实现思想就是定义迭代器的 + - = 等操作,要求能够检查边界,跳到另一个缓存区去

 

operator -  得到 A 与 B 之间有多少个元素:

B - A = 每个缓冲区放的元素个数 * AB之间完整的缓存区数量 + 末尾 buffer 的元素量 + 起始 buffer 的元素量

++ 与 -- 的实现,基本都是由 后 ++ 调用 前 ++后 -- 调用 前 -- 。 

 

deque的指针是一种随机访问指针,所以应该支持 +n 操作,重载 += 与 + 操作。-= 可以利用 += 代码实现。

self& operator-= (difference_type n)
{ return *this += -n; }

self operator- (difference_type n) const
{
    self tmp = *this;
    return tmp -= n;
}

reference operator[] (difference_type n) const
{ return *(*this + n); }

GNU4.9中,deque不允许指定 buffersize ,只提供两个模板参数。

二、Stack 和 Queue

  • queue 和 stack 都是基于 deque 实现,(内含一个deque,并限制某些操作)技术上本质为容器适配器。
  • 因为只能先进先出或者先进后出,不允许遍历,所以不提供迭代器   (声明 iterator 时会报错)

其中数据为默认类型为 deque 的容器 c,所有的对 queue 和 stack 的操作都是转调用 c 的类方法去做

本质上能完成这些转调用方法的容器都可以作为底层容器去实现 queue 。

  • list 和 deque 都可以作为底层容器实现 stack 和 queue。
  • stack 可以选择 vector 作为底层结构,queue 不可选择 vector 作为底层结构。

在声明 stack 和 queue 时,其底层容器类型 Sequence 作为模板参数,只要未涉及不能实现的相关操作,编译时其实都能通过。

猜你喜欢

转载自blog.csdn.net/SimonxxSun/article/details/85245620