首页 > 其他分享 >mystl之deque容器

mystl之deque容器

时间:2023-07-04 21:24:16浏览次数:33  
标签:deque const iterator 容器 void value mystl type

deque

代码仓库:https://github.com/sjz-hub/mystl

简介

  • deque是双端队列,c++标准STL容器的一种
  • 特点
    • 双向访问:支持在队列的两端进行高效的插入和删除操作
    • 内部插入:支持在内部进行插入和删除操作,但是性能不如list
    • 随机访问:支持[]和at(),但是性能不如vector

实现原理

  • 双端队列容器的底层结构是维护多个内存块(缓冲区),每个内存块都是一个存储指定类型数据的数组,多个内存块整体就是一个deque

image

  • 整体架构如上所示,每个内存块的长度大小一样,可以存放元素的数量也是一样,假定存放的数据类型为T,则缓冲区也就是内存块的类型为T*,则map_的类型为T**

  • 当向deque中放入元素空间不足时,会重新申请缓冲区,并让map_指向这些所有的缓冲区

  • deque类的成员变量为

    • iterator begin_ 指向实际的第一个节点
    • iterator end_指向实际的最后一个节点的下一个节点
    • T** map_ 存储所有缓冲区的地址
    • size_t map_size_ 存储的是map_数组的长度大小
  • iterator结构

    • T* cur 表示当前迭代器指向的哪一个具体节点
    • T* first表示当前迭代器所指节点的内存块的第一个元素地址
    • T* last表示当前迭代器所指节点的内存块最后一个元素的下一个地址
    • T** node存储的是缓冲内存块的地址

image

常见操作的原理

  • deque内部插入元素,会根据插入位置执行不同的策略
    • 插入位置在deque的前半段,则将该位置前面的元素依次前移,然后在该位置插入元素
    • 插入位置在deque的后半段,则将该位置后面的元素依次后移,然后在该位置插入元素
  • 删除元素,和插入元素差不多,都是根据删除位置的不同决定是将元素后移还是前移

迭代器实现的方法

方法名 含义
deque_iterator() noexcept 构造函数,四个成员置为nullptr
deque_iterator(value_pointer v, map_pointer n) 构造函数,cur=v,first=n,last=n+buff_size,node=n
deque_iterator(const iterator& rhs) 拷贝构造函数
deque_iterator(iterator&& rhs) noexcept 移动构造函数
deque_iterator(const const_iterator& rhs) 拷贝构造函数
self& operator=(const iterator& rhs) 拷贝赋值运算符
void set_node(map_pointer new_node) 转到另一个缓冲区,对node,first,last进行重置,但是不理解为什么不对cur重置
reference operator*() const 重载运算符
pointer operator->() const 重载运算符
difference_type operator-(const self& x) const 重载运算符
self& operator++() 重载运算符
self operator++(int) 重载运算符
self& operator--() 重载运算符
self operator--(int) 重载运算符
self& operator+=(difference_type n) 重载运算符
self operator+(difference_type n) const 重载运算符
self& operator-=(difference_type n) 重载运算符
self operator-(difference_type n) const 重载运算符
reference operator[](difference_type n) const 重载运算符
bool operator==(const self& rhs) const 重载运算符
bool operator< (const self& rhs) const 重载运算符
bool operator!=(const self& rhs) const 重载运算符
bool operator> (const self& rhs) const 重载运算符
bool operator<=(const self& rhs) const 重载运算符
bool operator>=(const self& rhs) const 重载运算符

deque类实现的public方法

方法名 含义
deque() 创建包含0个元素的deque
explicit deque(size_type n) 创建包含n个默认值的deque
deque(size_type n, const value_type& value) 创建包含n个指定值的deque
template <class IIter, typename std::enable_if< mystl::is_input_iterator::value, int>::type = 0> deque(IIter first, IIter last) 使用两个迭代器之间的值进行初始化
deque(std::initializer_list<value_type> ilist) 使用列表的方式进行初始化
deque(const deque& rhs) 拷贝构造函数
deque(deque&& rhs) noexcept 移动构造函数
deque& operator=(const deque& rhs); 拷贝赋值运算符
deque& operator=(deque&& rhs) 移动赋值运算符
deque& operator=(std::initializer_list<value_type> ilist) 列表的形式赋值
~deque() 析构函数,释放所有空间
iterator begin() noexcept
const_iterator begin() const noexcept
iterator end() noexcept
const_iterator end() const noexcept
reverse_iterator rbegin() noexcept
const_reverse_iterator rbegin() const noexcept
reverse_iterator rend() noexcept
const_reverse_iterator rend() const noexcept
const_iterator cbegin() const noexcept
const_iterator cend() const noexcept
const_reverse_iterator crbegin() const noexcept
const_reverse_iterator crend() const noexcept
bool empty() const noexcept 判断容器是否为空
size_type size() const noexcept 返回容器元素的个数
size_type max_size() const noexcept 返回容器包含元素的最大个数
void resize(size_type new_size) 重置容器大小,不足的填充默认值
void resize(size_type new_size, const value_type& value); 重置容器大小,不足的填充value
void shrink_to_fit() noexcept; 减少容器容量,其实就是减少缓冲区的数量
reference operator[](size_type n) 访问元素,返回引用
const_reference operator[](size_type n) const 访问元素,返回const引用
reference at(size_type n) 访问元素
const_reference at(size_type n) const 访问元素
reference front() 返回队头
const_reference front() const 返回const队头
reference back() 返回队尾
const_reference back() const 返回const队尾
void assign(size_type n, const value_type& value) 重新分配容器,变为n个value,并且重置缓冲区
template <class IIter, typename std::enable_if< mystl::is_input_iterator::value, int>::type = 0> void assign(IIter first, IIter last) 重置容器,变为两个迭代器之间的值
void assign(std::initializer_list<value_type> ilist) 使用列表的方式重置容器
template <class ...Args> void emplace_front(Args&& ...args); 在最前面创建元素
template <class ...Args> void emplace_back(Args&& ...args); 在最后面创建元素
template <class ...Args> iterator emplace(iterator pos, Args&& ...args); 在position前面插入一个元素,返回插入位置的迭代器
void push_front(const value_type& value); 在头部插入元素
void push_back(const value_type& value); 在尾部插入元素
void push_front(value_type&& value) 在头部插入元素
void push_back(value_type&& value) 在尾部插入元素
void pop_front(); 弹出头部元素
void pop_back(); 弹出尾部元素
iterator insert(iterator position, const value_type& value); 在position前面插入value,返回插入元素的迭代器
iterator insert(iterator position, value_type&& value) 在position前面插入value,返回插入元素的迭代器
void insert(iterator position, size_type n, const value_type& value); 在position前面插入n个value
template <class IIter, typename std::enable_if< mystl::is_input_iterator::value, int>::type = 0> void insert(iterator position, IIter first, IIter last) 在position前面插入两个迭代器之间的值
iterator erase(iterator position); 删除该迭代器的值,并返回该位置新的迭代器
iterator erase(iterator first, iterator last); 删除[first,last)的值,并返回新的first迭代器
void clear(); 删除整个容器,并且调用shrink_to_fit()放弃多余的空间
void swap(deque& rhs) noexcept; 交换两个迭代器

deque类实现的private帮助函数

方法名 含义
map_pointer create_map(size_type size); 创建一个含有size个T*的数组,返回这个数组的首地址
void create_buffer(map_pointer nstart, map_pointer nfinish); 为[nstart,nfinsh] 中的每一个元素都赋值一个大小为buffer_size的数组首地址,都是new出来的
void destroy_buffer(map_pointer nstart, map_pointer nfinish) 释放[nstart,nfinsh]中每个元素对应的数组空间,并都置为nullptr
void map_init(size_type nelem); deque应该可以包含eElem个元素,分配合适数量的缓冲区(最小一般不能小于8),算出来的缓冲区个数需要向上取整,并且最后还要+2,在和8取最大值。定义nstart,nfinsh都是map_pointer,实际指向的分别是应该是正好缓冲区的开始和缓冲区的结束,并对这个[nstart,nfinsh]进行new,然后赋值begin_和end_的四个成员
void fill_init(size_type n, const value_type& value); 调用map_init(n)进行初始化,并将对应位置都赋值为value
template void copy_init(IIter, IIter); 创建缓冲区,并将对应[first,last)的内容拷贝过来
void fill_assign(size_type n, const value_type& value); 重新分配缓冲区,并将值都变为value
template void copy_assign(IIter first, IIter last); 重新分配缓冲区,并将值变为[first,last)
template <class... Args> iterator insert_aux(iterator position, Args&& ...args); 在position前面插入一个值,如果position在前半段,就将前面的值向前移动,如果在后半段,就将后面的值向后移动,返回插入的元素的迭代器
void fill_insert(iterator position, size_type n, const value_type& x); 在position前面插入n个x,如果postion在前半段,则前面元素前移,如果在后半段,则后面元素后移。
template void copy_insert(iterator, FIter, FIter); 在position前面插入两个迭代器之间的值,如果postion在前半段,则前面元素前移,如果在后半段,则后面元素后移
template void insert_dispatch(iterator, IIter, IIter); 在iterator前面插入两个迭代器之间的值,左闭右开,如果要插入的位置在前半段,就保证开头位置空间有n个空闲,如果插在后半段,九保证结尾位置空间有n个空闲空间,n是两个迭代器之间元素的个数
void require_capacity(size_type n, bool front); front为true表示在队头,为false表示在队尾,看看是否还有n个元素的空间,如果没有,则创建新的缓冲区来确保可以添加n个元素
void reallocate_map_at_front(size_type need); 重新分配map,map_size的大小变为了原先的2倍和原先大小+need_buffer+DEQUE_MAP_INIT_SIZE的最大值,并且将begin_和end_分别指向中间的部分,并且对新的区域进行重新分配新的buffer,并将原先的buffer复制过来,删除原先的map,更新成员变量
void reallocate_map_at_back(size_type need); 和void reallocate_map_at_front(size_type need);差不多只不过是在后面加而已

代码仓库:https://github.com/sjz-hub/mystl

标签:deque,const,iterator,容器,void,value,mystl,type
From: https://www.cnblogs.com/sunjianzhao/p/17527048.html

相关文章

  • 2023容器网络趋势:CNI网络插件逐渐普及,Kube-OVN受欢迎度持续攀升
    今年,Kube-OVN社区联合OSCHINA、云原生社区共同发起了《2022-2023容器网络使用情况调研》,得到了大批K8s/容器网络技术人员的关注。本调研旨在更加直观地了解各行业企业容器网络的使用现状,以及Kube-OVN在社区用户中的使用情况,以便更全面地评估容器网络发展方向,更有针对性地规划Kub......
  • 条件注解之@ConditionalOnProperty注解:通过配置文件的配置来控制配置类是否加入spring
    一、条件注解分类常见的@ConditionalOnxxx开头的注解我们称之为条件注解,常见的条件注解有class条件注解:@ConditionalOnClassbean条件注解:@ConditionalOnBean属性条件注解:@ConditionalOnProperty…@ConditionalOnProperty:如果有指定的配置,条件生效;@ConditionalOnBean:如果......
  • docker命令、容器挂载、镜像制作、docker compose、docker私有仓库
    服务相关命令--开启dockersystemctlstartdocker--关闭dockersystemctlstopdocker--查看docker状态systemctlstatusdocker--重启systemctlrestartdocker--开机启动dockersystemctlenabledocker镜像相关命令--查看镜像dockerimages--搜索镜像以......
  • shell脚本:将运行容器的日志输出到文件清理服务器上的符合条件的docker镜像
    采集容器日志的shell脚本内容为:点击查看代码#!/bin/bashexportLANG=zh_CN.gb18030.~/.bash_profile#日志放置目录log_path=/aa/bb/cc/dd/eetodaydate=$(date+%Y%m%d)nowdate=$(date+%Y%m%d%H%M)#pod列表dube_pod_id='xx1-servicexx2-servicexx3-servicexx4-se......
  • 开发软件 --- java web 容器
    JavaWeb容器是一种运行JavaWeb应用程序的环境,提供对Servlet和JSP等技术的类库支持。以下是一些常见的JavaWeb容器:轻量级 ApacheTomca流行的开源轻量部分支持的javaweb容器。支持Servlet、JSP和WebSocket等技术。Jetty高性能的开源轻量部分支持的java......
  • PowerShell系列四:容器操作
    容器容器是一个很通用的概念。比如文件、文件夹、注册表、磁盘分区、数组、hash表、命名空间、用户组、OU、数据库、数据表等等,它们的共同点就是包含了数据。在PowerShell中一切都是从"PSDrive"开始的,您熟悉了操作PSDrive,基本就涵盖了对资源的操作。Get-PSDrive#输出Name......
  • 可视化容器管理工具-portainer.io使用
    续docker日常使用指南背景当我们开始使用docker后,我们的机器上镜像和容器会越来越多,或者有时候我们有多台开发机的时候,单纯使用命令行去管理镜像和容器就变得麻烦了,这时,我们就可以选择一些可视化的容器管理工具来保护我们为数不多的头发了。portainer.io就是这方面的一个不错的......
  • Spring容器获取Bean的9种方式
    1前言随着SpringBoot的普及,Spring的使用也越来越广,在某些场景下,我们无法通过注解或配置的形式直接获取到某个Bean。比如,在某一些工具类、设计模式实现中需要使用到Spring容器管理的Bean,此时就需要直接获取到对应的Bean。本文为大家整理汇总了常见的获取Bean的方式,并提供一些优......
  • Docker|容器与Docker基础知识
    Docker|基础知识从虚拟机开始我们知道和一个单纯的应用程序相比,操作系统是一个很重而且很笨的程序,简称笨重,有多笨重呢?我们知道操作系统运行起来是需要占用很多资源的,刚装好的系统还什么都没有部署,单纯的操作系统其磁盘占用至少几十G起步,内存要几个G起步。假设我有一台机器,16G......
  • 容器生命周期配置
    1、容器启动命令spec:  affinity:{}  containers:  - args:    -whiletrue;doechohello;sleep10;done    command:    -/bin/sh    --c    image:nginx:latest    imagePullPolicy:IfNotPresent ......