STL源码剖析——deque的实现
来源:互联网 发布:圣火名尊法器进阶数据 编辑:程序博客网 时间:2024/06/07 02:17
deque简介
deque是一个双向开口的容器,可在头尾两端插入和删除元素,deque由动态的连续空间组合而成,因为迭代器的良好设计,提供了随机访问,造成一种deque为连续空间的假象
deque的数据结构
deque有一个二级指针map,map指向一小块空间,其中的每个元素都是指针,指向一段连续线性空间,称为缓冲区,缓冲区为deque存储的主体,其中存放元素
tempalte <class T, class Alloc = alloc>class deque {public: typedef T value_type; typedef T* pointer; typedef T** map_pointer;protected: iterator start; iterator finish; map_pointer map; size_type size; //map内指针个数 ......}
iterator 结构如下:
template <class T>class deque_iterator {public: typedef T** map_pointer; T* cur; //指向所指缓冲区当前元素 T* first; //首元素 T* last; //尾元素后一个 map_pointer node; //指向控制中心}
用图表示如下
deque的主要操作
1.push_front
当start指向的缓冲区无备用空间时,执行push_front_aux push_front_aux
操作如下:
判断map前端的备用节点是否充足,如果充足,则再分配一个缓冲区,start.node - 1指向它,然后改节点,构造元素即可
如果map前端备用节点不足,如果map_size够大,则并不需要重新分配map, 只需要移动map中的元素即可,最后重置start, finish迭代器
即可
如果map_size不够大,则要重新分配map
2.push_back
操作与push_front类似
3.pop_front
void pop_front() { if (start.cur != start.last - 1) { //第一缓冲区有多个元素 destroy(start.cur); ++start.cur; } else pop_front_aux();}void pop_front_aux() { destroy(start.cur); deallocate_node(start.first); //回收缓冲区空间 start.set_node(start.node + 1); //重置迭代器 start.cur = start.first;}
4.pop_back
void pop_back() { if (finish.cur != finish.first) { //最后缓冲区有元素 --finish.cur; destroy(finish.cur); } else pop_back_aux();}void pop_back_aux() { deallocate_node(finish.first); //回收缓冲区空间 finish.set_node(finish.node - 1); //重置迭代器 finish.cur = finish.last - 1; destroy(finish.cur);}
deque迭代器完整实现
template <class T>class deque_iterator {public: typedef deque_iterator<T> iterator; typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef T* pointer; typedef T& reference; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef deque_iterator self; T* cur; //指向所指缓冲区当前元素 T* first; //首元素 T* last; //尾元素后一个 map_pointer node; //指向控制中心 deque_iterator():cur(0), first(0), last(0), node(0){} deque_iterator(const deque_iterator& other): cur(other.cur), first(other.first), last(other.last), node(other.node){} static size_t buffer_size() { return deque_buffer_size(sizeof(T)); } //重新设置指向管控中心的指针,修改first, last指向缓冲区 void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = *new_node + (difference_type)buffer_size(); } reference operator* () const { return *cur; } pointer operator-> () const { return &(operator*()); } difference_type operator- (const self& x) const { return difference_type((buffer_size() * (node - x.node - 1)) + (cur - first) + (x.last - x.cur)); } //前置++ self& operator++ () { ++cur; if (cur == last) { set_node(node + 1); cur = first; } return *this; } //后置++ self operator++ (int) { self temp = *this; ++*this; return temp; } //前置-- self& operator-- () { if (cur == first) { set_node(node - 1); cur = last; } --cur; return *this; } //后置-- self operator-- (int) { self temp = *this; --*this; return temp; } //实现随机存取 self& operator+= (difference_type n) { difference_type offset = n + cur - first; size_t size = buffer_size(); if (offset >= 0 && offset < size) cur += n; else { //不在同一缓冲区内 difference_type node_offset = offset > 0 ? offset / size : -difference_type((-offset - 1) / size) - 1; //重置node,设置cur指向 set_node(node + node_offset); cur = first + (offset - node_offset * size);//offset正负都适用 } return *this; } self operator+ (difference_type n) const { self temp = *this; return temp += n; } self& operator-= (difference_type n) { return *this += -n; } self operator- (difference_type n) const { self temp = *this; return temp -= n; } //重载[],随机存取 reference operator[] (difference_type n) const { return *(*this + n); } bool operator== (const self& x) { return cur == x.cur; } bool operator!= (const self& x) { return cur != x.cur; } bool operator< (const self& x) { return (node == x.node) ? (cur < x.cur) : (node < x.node); }};
为了将deque的迭代器使用起来看似是普通指针需要费些功夫
小结:
由deque的构造我们可以很自然的想到,用deque作为底层容器来实现stack,queue,对于stack,queue的所有操作只需要对deque转调用即可
阅读全文
0 0
- STL源码剖析——deque的实现
- 《STL源码剖析》deque的实现
- STL源码剖析——deque
- STL源码剖析——deque的实现原理和使用方法详解
- STL 源码剖析 deque实现源码
- STL源码剖析---deque
- STL源码剖析---deque
- STL源码剖析---deque
- STL源码剖析---deque
- STL源码剖析---deque
- STL源码剖析---deque
- STL源码剖析----deque
- STL源码剖析---deque
- STL源码—deque
- STL源码—deque
- STL源码剖析 deque的中控器
- STL源码剖析——序列容器之deque
- STL之deque源码剖析
- Python之函数简析(一)
- 基于zookeeper的服务注册中心
- Java面试之Spring面试知识点
- Java开发中的23种设计模式详解(转)
- Android设备ID简析
- STL源码剖析——deque的实现
- [BFS] POJ 3087
- 字符编码中的一些概念辨析
- 判断scroll是否滚动到底部以及实现回到顶部
- 蓝桥杯 算法提高 实数相加
- Vim命令合集(转)
- 大整数相加
- It's no longer allowed to omit the '-loader' suffix when using loaders.
- Kylin 2.0升级总结