deque源码2(deque迭代器、deque的数据结构)
deque源码2(deque迭代器、deque的数据结构)
deque源码3(deque的构造与内存、ctor、push_back、push_front)
deque源码4(deque元素操作:pop_back、pop_front、clear、erase、insert)
deque的迭代器
deque是分段连续空间,维持其"整体连续"的假象任务,落在了迭代器的operator++和operator--两个运算子身上。
对于operator:1、必须能够指出分段连续空间(即缓冲区)在哪里
2、必须能够判断自己是否已经处于其所在缓冲区的边缘,在跳跃时,必须掌握控制中心。
如下图:
template <class T,class Ref,class Ptr,size_t Bufsize>
struct __deque_iterator{ //为继承 std::iterator
typedef __deque_iterator<T,T&,T*,Bufsize> iterator;
typedef __deque_iterator<T,const T&,const T*,Bufsize> const_iterator;
static size_t buffer_size(){return __deque_buf_size(Bufsize,sizeof(T));} //未继承std::iterator,所以必须自行撰写五个必要的迭代器相应型别
typedef random_access_iterator_tag iterator_category; //
typedef T value_type; //
typedef Ptr pointer; //
typedef Ref renference; //
typedef size_t size_type;
typedef ptrdiff_t difference_type; //
typedef T** map_pointer; typedef __deque_iterator self; //保持与容器的联结
T* cur; //此迭代器所指之缓冲区中的现行(current)元素
T* first; //此迭代器所指之缓冲区中的头
T* last; //此迭代器所指之缓冲区中的尾(含备用空间)
map_pointer node; //指向管控中心
... inline size_t __deque_buf_size(size_t n,size_t sz){
return n!=? n:(sz<? size_t(/sz):size_t());
}
/*
n!=0,返回n,表示buffer_size由用户自定义
n=0,表示buffer_size使用默认值,那么:
sz<512,传回512/sz;
sz>=512,传回1
*/
};例如:产生一个deque<int>,令缓冲区大小为32,于是每个缓冲区可以容纳32/sizeof(int)=8个元素,经过增删操作,deque中包含20个元素,deque情况如下图:
start和finish分别指向deque的第一个缓冲区和最后一个缓冲区,20/8=3,所以map拥有3个节点,且最后一个缓冲区还有插入元素的空间。
用于迭代器内对各种指针运算都进行重载操作,所以各种运算算法都比较麻烦,特别是对于在缓冲区边缘的元素操作都需要调用set_node操作,来跳一个缓冲区。代码如下:
void set_node(map_pointer new_node){
node=new_node;
first=*new_node;
last=first+difference_type(buffer_size());
}重载运算符如下:
renference operator*() const {return *cur;} pointer operator->() const {return &(operator*());} difference_type operator-(const self& x)const{
return difference_type(buffer_size())*(node-x.node-)+(cur-first)+(x.last-x.cur);
} self& operator++(){
++cur; //切换下一个元素
if(cur==last){ //如果已达到所在缓冲区的尾端
set_node(node+); //利用set_node方法切换到下一个缓冲区
cur=first;
}
return *this;
}
self operator++(int){
self temp=*this;
++*this; //调用operator++
return temp;
} self& operator--(){
if(cur==first){ //如果达到缓冲区的头部
set_node(node-); //利用set_node方法切换到上一个缓冲区
cur=first;
}
--cur;
return *this;
}
self operator--(int){
self temp=*this;
--*this; //调用operator--
return temp;
} self& operator+=(difference_type n){ //实现随机存取、迭代器可以直接跳跃n个距离
difference_type offset=n+(cur-first);
if(offset>=&&offset<difference_type(buffer_size())) //目标位置在统一缓冲区
cur+=n;
else{ //目标位置在统一缓冲区
difference_type node_offset=offset>?
offset/difference_type(buffer_size()):-difference_type((-offset-)/buffer_size())-;
set_node(node+node_offset); //切换至正确的节点
cur=first+(offset-node_offset*difference_type(buffer_size()); //切换至正确的元素
}
return *this;
}
self operator+(difference_type n) const{
self temp=*this;
return temp+=n; //调用operator+=
} self& operator-=(difference_type n){
return *this+=-n;
}
self operator-(difference_type n) const{
self temp=*this;
return temp-=n; //调用operator-=
} //随机存取第n个元素
reference operator[](difference_type n)const {return *(*this+n);} bool operator==(const self& x)const{return cur==x.cur;}
bool operator!=(const self& x)const{return !(*this==x);}
bool operator<(const self& x)const{
return (node==x.node)?(cur<x.cur):(node<x.node);
}
deque的数据结构
deque除了维护上文map的指针外,还要维护start,finish两个迭代器(上图2可见),分别指向第一个缓冲区的第一个元素和最后一个缓冲区的最后一个元素的下一个位置(可能还有备用空间),此外,它当然也必须记住目前的map大小,因为一旦map所提供的节点不足,就必须重新配置更大的一块map。
template <class T,class Alloc=alloc,size_t BufSiz=>
class deque{
public:
typedef T value_type;
typedef value_type* pointer;
typedef size_t size_type;
public:
typedef __deque_iterator<T,T&,T*,BufSiz> iterator;
protected:
typedef pointer* map_pointer;//元素的指针的指针
protected:
iterator start; //表示第一个节点
iterator finish; //表示最后一个节点
map_pointer map; //指向map,map是块连续空间,其每个元素都是指针,指向一个节点
size_type map_size; //map内有多个指针
... public:
iterator begin(){return start;}
iterator end(){return finish;} reference operator[](size_type n){
return start[difference_type(n)]; //调用operator[]
}
reference front(){return *start;} //调用operator*
reference back(){
iterator temp=finish;
--temp; //调用operator--
return *temp; //调用operator*
} size_type size() const{return finish-start;} //调用operator-
size_type max_size() const{return size_type(-);} bool empty() const{return finish==start;}
};
deque源码2(deque迭代器、deque的数据结构)的更多相关文章
- deque源码4(deque元素操作:pop_back、pop_front、clear、erase、insert)
deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...
- deque源码3(deque的构造与内存、ctor、push_back、push_front)
deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...
- deque源码1(deque概述、deque中的控制器)
deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...
- STL源码分析之迭代器
前言 迭代器是将算法和容器两个独立的泛型进行调和的一个接口. 使我们不需要关系中间的转化是怎么样的就都能直接使用迭代器进行数据访问. 而迭代器最重要的就是对operator *和operator-&g ...
- STL源码剖析:迭代器
准备知识 什么是迭代器? 迭代器是链接容器和算法的桥梁,所有的算法都通过迭代器操作容器中的数据 迭代器是一种智能指针,最重要的操作符重载就是operator*,operator-> 迭代器的实现 ...
- 给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器
今天的主角是HashSet,Set是什么东东,当然也是一种java容器了. 现在再看到Hash心底里有没有会心一笑呢,这里不再赘述hash的概念原理等一大堆东西了(不懂得需要先回去看下Has ...
- 结合JDK源码看设计模式——迭代器模式
前言: Iterator翻译过来就是迭代器的意思.在前面的工厂模式中就介绍过了iterator,不过当时介绍的是方法,现在从Iterator接口的设计来看,似乎又是一种设计模式,下面我们就来讲讲迭代器 ...
- HDFS源码分析:NameNode相关的数据结构
本文主要基于Hadoop1.1.2分析HDFS中的关键数据结构. 1 NameNode 首先从NameNode开始.NameNode的主要数据结构如下: NameNode管理着两张很重要的表: 1) ...
- 动图+源码,演示Java中常用数据结构执行过程及原理
最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...
随机推荐
- final,static,abstract
一.final 1.可以修饰属性,表示常量,其值在运行期间不允许改变.常量必须赋初始值,初始值可以在声明出,构造方法的任意一个地方赋 优点:增强程序的可读性,可维护性 2.可以修饰方法,表示该方法不能 ...
- dede网站安全要做的四件事
1,把安装install的文件夹删除:2,关闭member系统,禁止member文件写入:3,把data文件外移到网站根目录之外:4,把included和plus目录的写入权限关闭. 转载自:http ...
- 探索微信小程序之路
记录一下每日的知识点,时不时温习一下. 视图与渲染对于页面中的数据,以json的方式存放在js文件的data中 判断的使用: <view wx:if='{{true}}'> 为真时显示 & ...
- appium:运行脚本时,报404的解决办法
对于报404的错,不要怀疑,在环境正常的情况下,一定是你的端口被占用了. 就用:查看端口:netstat -aon|findstr 5037 查看进程:tasklist /fi "PID e ...
- PHP中this,self,parent的区别
{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行P ...
- python 文件与数据格式化
https://www.cnblogs.com/li-zhi-qiang/p/9269453.html 文件和数据格式化 https://www.cnblogs.com/li-zhi-qi ...
- python jieba库
https://www.cnblogs.com/snailclimb/p/9086433.html https://blog.csdn.net/codejas/article/details/8035 ...
- 转 SaaS应用十大关键NFR - 第1部分
非功能需求(SaaS的NFR)是跨越应用功能的跨越所有模块和功能的要求.这些要求深入到应用程序的架构,这是他们得到解决的地方.因此,在SaaS架构阶段之前了解这些NFR对于特定应用程序很重要,因此应用 ...
- 在CentOS 7上安装和使用GlusterFS
GlusterFS aggregates various storage servers over Ethernet or Infiniband RDMA interconnect into one ...
- #227 Generate Random Whole Numbers within a Range
我们之前生成的随机数是在0到某个数之间,现在我们要生成的随机数是在两个指定的数之间. 我们需要定义一个最小值和一个最大值. 下面是我们将要使用的方法,仔细看看并尝试理解这行代码到底在干嘛: Math. ...