deque源码1(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的数据结构)的更多相关文章

  1. 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_ ...

  2. deque源码3(deque的构造与内存、ctor、push_back、push_front)

    deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...

  3. deque源码1(deque概述、deque中的控制器)

    deque源码1(deque概述.deque中的控制器) deque源码2(deque迭代器.deque的数据结构) deque源码3(deque的构造与内存.ctor.push_back.push_ ...

  4. STL源码分析之迭代器

    前言 迭代器是将算法和容器两个独立的泛型进行调和的一个接口. 使我们不需要关系中间的转化是怎么样的就都能直接使用迭代器进行数据访问. 而迭代器最重要的就是对operator *和operator-&g ...

  5. STL源码剖析:迭代器

    准备知识 什么是迭代器? 迭代器是链接容器和算法的桥梁,所有的算法都通过迭代器操作容器中的数据 迭代器是一种智能指针,最重要的操作符重载就是operator*,operator-> 迭代器的实现 ...

  6. 给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器

    今天的主角是HashSet,Set是什么东东,当然也是一种java容器了.      现在再看到Hash心底里有没有会心一笑呢,这里不再赘述hash的概念原理等一大堆东西了(不懂得需要先回去看下Has ...

  7. 结合JDK源码看设计模式——迭代器模式

    前言: Iterator翻译过来就是迭代器的意思.在前面的工厂模式中就介绍过了iterator,不过当时介绍的是方法,现在从Iterator接口的设计来看,似乎又是一种设计模式,下面我们就来讲讲迭代器 ...

  8. HDFS源码分析:NameNode相关的数据结构

    本文主要基于Hadoop1.1.2分析HDFS中的关键数据结构. 1 NameNode 首先从NameNode开始.NameNode的主要数据结构如下: NameNode管理着两张很重要的表: 1)  ...

  9. 动图+源码,演示Java中常用数据结构执行过程及原理

    最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想用动画来绘制数据流转过程. 主要基于jdk8, 可能会有些特性与jdk7之前不相同, 例如LinkedList Linke ...

随机推荐

  1. java上传文件常见几种方式

    1.ServletFileUpload 表单提交中当提交数据类型是multipare/form-data类型的时候,如果我们用servlet去做处理的话,该http请求就会被servlet容器,包装成 ...

  2. 《Miracle_House》团队项目系统设计改进

    一.团队项目系统设计改进: 1.分析项目系统设计说明书初稿的不足,特别是软件系统结构模型建模不完善内容: 对于原文档中,设计图中存在的错误以及文字描述不准确的地方进行了修改. 2. 团队项目Githu ...

  3. 第九周助教工作总结——NWNU李泓毅

    1.助教博客链接: https://www.cnblogs.com/NWNU-LHY/ 2.作业要求博客链接: https://www.cnblogs.com/nwnu-daizh/p/1072688 ...

  4. 有return的情况下try catch finally的执行顺序(转)

    结论:1.不管有没有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...

  5. Redis与SpringBoot整合

    添加Redis相关jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  6. 第46章:MongoDB-监控应用状态

    ① MongoDB监控  1 db.serverStatus() 查看实例运行状态(内存使用.锁.用户连接等信息) 通过比对前后快照进行性能分析 "connections" # 当 ...

  7. GitHub上高质量项目

    scribejava/scribejava:一个简单的 Java 实现的 OAuth/OAuth2 库winterbe/java8-tutorial:绝对值得一看的Java8指南.教程javaee-s ...

  8. asp.net项目配置Web.config,支持JSON

    VS2013新建的web项目不支持直接下载json文件,可以在项目的web.config下插入如下的配置信息. <configuration> <system.web> < ...

  9. ServiceStack.OrmLite 入门(一)

    软件环境: Win7 x64 SP1 SQL Server 2008r2 Visual Studio 2017 Professional 目标:取出示例数据库 ReportServer 的表 Role ...

  10. Linux时间戳转换成BCD码(转载)

    #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> / ...