STL_deque_stack_queue

news2024/11/26 20:31:08

Deque

deque容器(双端队列)
​deque是一种双向开口的分段连续线性空间(对外号称连续,使用者无法感知它是分段的)。deque支持从头尾两端进行元素的插入和删除。deque没有容量的概念,因为它是动态地以分段连续空间组合而成的。随时可以增加一段新的空间并连接起来。

deque用vector存储buffer,当前vector容量满了之后,vector二倍扩容,将原始数据拷贝到新数据的中段,
使得map 可以向两端扩容
在这里插入图片描述

deque 的迭代器

deque的迭代器是一个class

  • node指向控制中心map,当迭代器++或-- 时,可以跳转到另一个分段
  • first last指向当前所在buffer的头和尾,标记缓冲区的边界,当迭代器在走到当前buffer边界,下一步需要走到其他buffer(通过node)
  • cur 当前迭代器指向的元素
template<class T,class Ref,class Ptr,size_t BufSiz>
struct __deque_iterator
{
	typedef random_access_iterator_tag iterator_category; //1
	typedef T value_type;	//2
	typedef Ptr pointer;	//3
	typedef Ref reference;	//4
	typedef size_t size_type;	
	typedef ptrdiff_t difference_type; //5
	typedef T** map_pointer;
	typedef __deque_iterator self;

	T* cur;
	T* first;
	T* last;
	map_pointer node;
	...
};

deque源码

template<class T,class Alloc=alloc,size_t BufSiz=0>
class deque
{
public:
	typedef T value_type;
	typedef __deque_iterator<T,T&,T*,BufSiz> iterator;

protected:
	typedef pointer* map_pointer; //T**
	iterator start;
	iterator finish;
	map_pointer map;
	size_type map_size;

public:
	iterator begin(){return start;}
	iterator end(){return end;}
	size_type size(){return finish-start;}
	...
};

​ 为了维护这种整体连续的假象,带价就是迭代器的类型会比较复杂。即采用map(类型为T**)作为主控。map实际上是一块大小连续的空间,其中每一个元素,我们称之为node,每个node都指向了另一端连续线性的空间(上图的buffer),buffer才是deque真正存储空间的地方。

​ 其中buffer大小的确定:

/*
n不为0,传回n,buffersize由user确定
n为0,buffersize使用预设值,如果sz(sizeof(value_type))小于512,传回512/sz,否则就传回1
*/
inline size_t __deque_buf_size(size_t n,size_t sz)
{
	return n!=0?n:(sz<512?size_t(512/sz):size_t(1));
}

deque插入元素

deque::insert()插入函数首先判断传入迭代器的位置是处于容器前半部分还是后半部分,再插入进比较短的那一段。

deque::insert()

iterator inset(iterator position,const value_type& x)
{
	if(position.cur==start.cur){
		push_front(x);
		return start;
	}else if(position.cur==finish.cur){
		push_back(x);
		return finish
	}else{
		return insert_aux(position,x);
	}
}

若插入位置是容器首部,则直接push_front,位置是容器尾部,则直接push_back。其他情况则调用insert_aux方法:

template<class T,class Alloc,size_t BufSize>
typename deque<T,Alloc,BufSize>::iterator 
deque<T,Alloc,BufSize>::insert_aux(iterator pos,const value_type& x){
	difference_type index = pos-start; //安插点之前的元素个数
	value_type x_copy = x;
	if(index<size()/2){			//如果安插点之前的元素个数较少
		push_front(front());	//在最前端加入和第一元素同值的元素
		...
		copy(front2,pos1,front1); //元素搬移
	}else{					//安插点之后较少
		push_back(back());	//在尾端加入和最末元素同值的元素
		...
		copy_backward(pos,back2,back2); //元素搬移
	}
	*pos = x_copy;
	return pos;
}

deque如何模拟连续的空间:

reference operator[](size_type n){
	return start[difference_type(n)];
}

reference front(){
	return *start;
}
reference back(){
    iterator tmp = finish;
    --temp;
    return *temp;
}

size_type size()const{
	return finish-start;
}

bool empty()const{
	return finish==start;
}

重要的操作符重载: -

  • 重载 判断两个迭代器之间的距离:
    两个迭代之间的buffer数量 + it1 到其尾部的长度 + it2 到其头部的长度
reference operator*()const{
   return *cur;
}

pointer operator->()const{
   return &(operator*());
}

//两根iterator之间的距离相当于  两根iterators之间的buffers的总长度+it1至其buffer尾部长度+it2至其buffer头部的长度
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 tmp = *this;
   ++*this;
   return temp;
}

self& operator--(){
   --cur;
   if(cur==first){
   	set_node(node-1); //跳到上一节点的尾节点
   	cur = last;
   }
   return *this;
}

self operator--(int){
   self tmp = *this;
   --*this;
   return temp;
}


void set_node(map_pointer new_node){
   node = new_node;
   first = *node;
   last = first+difference_type(buffer_size());
}

self& operator+=(difference_type n)
{
   difference_type offset = n+(cur-first);
   if(offset>=0&&offset<difference_type(buffer_size()))
   // 目标在同一buffer内
   cur +=n;
   else{
       // 目标不在同一buffer内
       difference_type node_offset = offset>0?offset/difference_type(buffer_size()):-difference_type((-offset-1)/buffer_size())-1;
       // 切换至正确的buffer内
       set_node(node+node_offset);
       // 切换至正确的元素
       cur = first+(offset-node_offset*difference_type(buffer_size()));
   }
   return *this;
}

self operator+(difference_type n){
   self tmp = *this;
   return temp+=n;
}

queue和stack默认封装了 deque
调用deque种的函数

queue

在这里插入图片描述

template<class T, class Sequence=deque<T>>
class queue {
public:
    typedef typename Sequence::value_type value_type;
    typedef typename Sequence::size_type size_type;
    typedef typename Sequence::reference reference;
    typedef typename Sequence::const_reference const_reference;
protected:
    Sequence c;     // 底层容器,默认是deque<T>
public:
    bool empty() const { return c.empty(); }
    size_type size() const { return c.size(); }
    reference front() { return c.front(); }
    const_reference front() const { return c.front(); }
    reference back() { return c.back(); }
    const_reference back() const { return c.back(); }
    void push(const value_type &x) { c.push_back(x); }
    void pop() { c.pop_front(); }
    // ...
};

stack

在这里插入图片描述

template<class T, class Sequence=deque<T> >
class stack {
public:
    typedef typename Sequence::value_type value_type;
    typedef typename Sequence::size_type size_type;
    typedef typename Sequence::reference reference;
    typedef typename Sequence::const_reference const_reference;
protected:
    Sequence c;// 底层容器,默认是deque<T>
public:
    bool empty() const { return c.empty(); }
    size_type size() const { return c.size(); }
    reference top() { return c.back(); }
    const_reference top() const { return c.back(); }
    void push(const value_type &x) { c.push_back(x); }
    void pop() { c.pop_back(); }
    // ...
};

也可以指定其他容器,例如list、vector作为stack和queue的底层容器,因为它们内部也实现了对应所需要的方法。

queue<int, list<int>> q1;
for (long i = 0; i < 10; ++i) {
   q1.push(rand());
}

stack<int, list<int>> s1;
for (long i = 0; i < 10; ++i) {
   s1.push(rand());
}

stack<int, vector<int>> s2;
for (long i = 0; i < 10; ++i) {
   s2.push(rand());
}

stack 和 queue 都不允许遍历,也不提供迭代器
stack 和queue实际调用的是容器的函数,如果容器没有实现stack和queue的功能,比如map、set没有实现stack种的功能,不可以选择set或map作为stack queue的底层结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1625792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同态加密原理解析

目录 1.数学介绍2.使用多项式环进行加密2.1 私钥和公钥的产生2.2 加密2.3 解密 3.同态计算3.1 同态加法3.2 同态乘法 1.数学介绍 同态加密方案基于一个难以计算的问题Ring Learning with Errorsred。这些方案中的数据在加密和未加密时都用多项式表示。 这里举一个简单的多项式…

最详细的 Windows 下 PyTorch 入门深度学习环境安装与配置 GPU 版 土堆教程

最详细的 Windows 下 PyTorch 入门深度学习环境安装与配置 CPU GPU 版 | 土堆教程 Windows 下 PyTorch 入门深度学习环境安装与配置 GPU 版 教程大纲如何使用此教程快速开始版本 Windows下判断有无NVIDIA GPU安装Anaconda作用流程下载安装 Anaconda 创建虚拟环境利用conda或者…

jmeter安装和简单使用

jmeter安装和简单使用 1. 安装 jmeter是基于Java开发的测试应用&#xff0c;其运行依赖于java环境&#xff0c;所以在下载运行jmeter前&#xff0c;先确保本机已经安装jdk或者jre&#xff0c;安装jdk步骤此处不描述。 下载jmeter&#xff1a; jmeter是Apache旗下的产品&…

电阻理论基础

电流的形成是电荷运动&#xff0c;电子方向相反&#xff0c;标量 电压&#xff1a;电势有参考点&#xff0c;是一个相对量 电阻的值不取决于电压和电流的&#xff0c; Ra表示标准电阻 R表示任意温度的电阻

数据结构:时间复杂度和空间复杂度

目录 1. 如何衡量一个算法的好坏2. 算法效率3. 时间复杂度3.1 时间复杂度的概念3.2 大O的渐进表示法3.3 推导大O阶方法3.4 常见时间复杂度计算举例 3.空间复杂度 1. 如何衡量一个算法的好坏 下面求斐波那契数列的算法好还是不好&#xff0c;为什么&#xff1f;该如何衡量一个算…

新书推荐机器学习大数据平台的构建、任务实现与数据治理

在大数据与机器学习日新月异的今天&#xff0c;构建稳定、安全、可扩展的数据平台已成为企业和研究机构的迫切需求。这本书应运而生&#xff0c;提供了详尽且实用的指南&#xff0c;帮助读者在云计算环境中构建、优化和治理大数据平台。 作者以清晰明了的写作风格&#xff0c;…

实现基于UDS LIN诊断协议的本地OTA升级

一、目标 在上篇文章LIN诊断实现MCU本地OTA升级_lin ota-CSDN博客中已经基于LIN诊断协议实现了通过PC端上位机对MCU进行本地的OTA升级&#xff0c;但是没有完全按照UDS协议实现。本篇将在上篇文章的基础上进行改进&#xff0c;实现基于UDS LIN诊断协议的本地OTA升级。本篇文章对…

C语言 | Leetcode C语言题解之第52题N皇后II

题目&#xff1a; 题解&#xff1a; struct hashTable {int key;UT_hash_handle hh; };struct hashTable* find(struct hashTable** hashtable, int ikey) {struct hashTable* tmp NULL;HASH_FIND_INT(*hashtable, &ikey, tmp);return tmp; }void insert(struct hashTabl…

nvm 使用教程

在任意目录中的空白处 按住Shift键不放&#xff0c;鼠标点击右键&#xff0c;在弹出的菜单中选择 “在此处打开 Powershell 窗口(S)”。 查看远程线上的nodejs版本 nvm ls available 查看自己安装的nodejs版本 nvm ls 切换nodejs版本号 nvm use 版本号 安装 xxx版本的nodej…

浅谈游戏机制

浅谈游戏机制 前言什么是游戏机制&#xff1f;机制组成机制类别结语 前言 最近在编写游戏开发文档的时候了解到游戏机制&#xff0c;第一次接触游戏机制的概念难免有些陌生&#xff0c;但感觉又跟常见&#xff0c;在网上查阅浏览了一些资料后了解到游戏机制还不止一个。 现在将…

Linux|Awk 变量、数字表达式和赋值运算符

引言 本部分[1]将深入学习 Awk 的高级应用&#xff0c;以应对更为复杂的文本或字符串过滤任务。将介绍包括变量、数值表达式和赋值运算符在内的 Awk 功能。 这些概念与你之前可能在诸如shell、C、Python等许多编程语言中接触过的概念并没有本质上的不同&#xff0c;所以你不必过…

【RAG 论文】Chain-of-Note:为 RAG 引入 CoT 让模型生成阅读笔记来提高面对噪音文档和未知场景的鲁棒性

论文&#xff1a;Chain-of-Note: Enhancing Robustness in Retrieval-Augmented Language Models ⭐⭐⭐ Tencent AI Lab, arXiv:2311.09210 文章目录 一、论文速读二、实现的细节2.1 Note Design2.2 Data Collection2.3 Model Training 三、实验结果3.1 QA Performance3.2 对 …

Python:解析pyserial串口通讯

简介&#xff1a;串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方式的扩展接口。串行接口 &#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简单&#…

全额退款20000,what?

接单的时候有多兴奋&#xff0c;退单的时候就有多落寞。今天我对客户全额退款了&#xff0c;跟踪了10天的项目正式结束。 这是我接单以来项目单价最高的一个项目&#xff0c;本来不太想接的&#xff0c;因为业务领域不擅长&#xff0c;又想挑战一下。兜兜转转找了几个人因为各种…

Python请求示例电商商品详情数据(API接口开发系列),从入门到实战

在电商系统中&#xff0c;商品详情数据通常通过API接口提供。以下是一个从入门到实战的Python请求示例&#xff0c;展示如何获取电商商品详情数据。 入门篇&#xff1a;理解API接口 首先&#xff0c;你需要了解API&#xff08;应用程序接口&#xff09;的基本概念。API允许不…

用Redis实现获取验证码,外加安全策略

安全策略 一小时内只能获取三次&#xff0c;一天内只能获取五次 Redis存储结构 代码展示 import cn.hutool.core.util.RandomUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Test; import org.spri…

JVM学习笔记(五)内存模型

目录 1、原子性 1.1 问题分析 1.2 解决方法 2、可见性 2.1 退不出的循环 2.2 解决办法 3、有序性 3.1 诡异的结果 3.2 解决办法 3.3 有序性理解 3.4 happens-before 4、CAS与原子类 4.1 CAS 4.2 乐观锁与悲观锁 4.3 原子操作类 5、synchronized 优化 5.1 轻量…

鸿蒙入门11-DataPanel组件

数据面板组件 用于将多个数据的占比情况使用 占比图 进行展示 参数 参数形式 &#xff1a; DataPanel( options:{ values: number[], max?: number, type?: DataPanelType } ) 参数名 参数类型 是否必填 默认值 参数描述 values number[] 是 - 数据值列表 最大支持…

Recommended Azure Monitors

General This document describes the recommended Azure monitors which can be implemented in Azure cloud application subscriptions. SMT incident priority mapping The priority “Blocker” is mostly used by Developers to prioritize their tasks and its not a…

zigbee cc2530的室内/矿井等定位系统RSSI原理

1. 定位节点软件设计流程 2. 硬件设计 cc2530 最小系统 3. 上位机 c# 设计上位机&#xff0c;通过串口连接协调器节点&#xff0c;传输数据到pc上位机&#xff0c;显示节点坐标信息 4. 实物效果 需要4个节点&#xff0c;其中一个协调器&#xff0c;两个路由器作为参考节点&a…