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 ...
随机推荐
- python 练习2
购物订单系统: #!usr/bin/env python # encoding: utf-8 import sys i = 0 inventory_dic = {'Car':1000,'SUV':50 ...
- JAVA实现等腰三角形
class Triangle { public static void main(String[] args) { for(int a=0; b<5; a++)//这个代表只有四行 { for( ...
- Python3 在操作excel时报PermissionError: [Errno 13] Permission denied: 'D:/workstation/yhdx_auto/config/case.xls'错误
此问题为文件被拒绝访问,主要是该文件已经被打开了.关闭此excel文件后在执行excel的相关操作就ok了.
- HDU-4763 Theme Section KMP
题意:求最长的子串E,使母串满足EAEBE的形式,A.B可以任意,并且不能重叠. 题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4763 思 ...
- springsecurity 源码解读 之 RememberMeAuthenticationFilter
RememberMeAuthenticationFilter 的作用很简单,就是用于当session 过期后,系统自动通过读取cookie 让系统自动登录. 我们来看看Springsecurity的过 ...
- PowerShell工作流学习-5-自定义活动
关键点: a)除了内置活动和自定义活动,还可以用C# 编写自定义活动,并将其包括在 XAML 工作流和脚本工作流中,若要将自定义活动添加到脚本工作流中,请使用 #Requires 语句的 Assemb ...
- Delphi XE7试用记录2
Delphi XE7试用记录2 万一博客中介绍了不少Delphi7以后的新功能测试,想跟着测试一下.每次测试建立一个工程,在窗体上放几个按钮,测试几个相关的功能,这样虽然简单明了,但日后查阅起来不方便 ...
- vue数据双向绑定
Vue的双向绑定是通过数据劫持结合发布-订阅者模式实现的,即通过Object.defineProperty监听各个属性的setter,然后通知订阅者属性发生变化,触发相应的回调. 整个过程分为以下几步 ...
- Linux下安装GEOS环境
1.下载对应版本的geos源码:http://download.osgeo.org/geos/ 2.下载后使用cd切换到源码目录解压:tar -xvf geosXXX.tar.gz 3.切换到解压后目 ...
- 编码符_new88
begin#239B38F58D59E401465E1FEE0AFA7AE2DD920EB6645F4A2075C7ABBBE2141B925668C9D635D90DE884907F4E52F921 ...