循环队列与循环双端队列

文章目录

  • 前言
  • 循环队列
  • 循环双端队列


前言

1、学习循环队列和循环双端队列能加深我们对队列的理解,提高我们的编程能力。
2、本文循环队列使用的是数组,循环双端队列用的是双向链表
3、题目连接:设计循环队列 ,设计循环双端队列。

循环队列

1、什么是循环队列?

循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

在这里插入图片描述

2、实现的功能

(1)MyCircularQueue(k): 构造器,设置队列长度为 k 。
(2)Front: 从队首获取元素。如果队列为空,返回 -1。
(3)Rear: 获取队尾元素。如果队列为空,返回 -1 。
(4)enQueue(value):向循环队列插入一个元素。如果成功插入则返回真。
(5)deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
(6)isEmpty(): 检查循环队列是否为空。
(7)isFull(): 检查循环队列是否已满。

3、设计
有两种方案:a:利用数组来存储数据,b:利用链表来存储数据
我们这里使用数组的方式
(1)我们设置一个头指针,和一个尾指针(指的时最后一个有数据位置的下一个位置,为什么不直接指向最后有数据那个位置呢?因为这样能更好的判断队列是否为空和队列是否已经满的情况),头指针(front),尾指针(rear),容量(k)。

(2) 为了解决尾指针指向最后一个数据后一个的问题,我们可以多申请一个空间,就不会使尾指针指的位置超出数组了,这个问题也叫假溢出。

(3)判断空,当front=rear时为空
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d05483fe9eb840fdad065ce02b088b52.png

(4)判断满,当 front=(rear+1)%(k+1) 为空

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d06eadb22f7048aa8ede33702d1e9548.png

(5)删除队头元素,使front=(front+1)%(k+1)即可, 也可以通过判断front是否在(k+1)的位置,在的话就使front=0,不在的话front=front+1即可

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/14aff520fd254a0a9b2751cf622e4a82.png

(6)进队,将数据放到数组下标rear位置上,然后使 rear=(rear+1)%(k+1) 即可,原理同上。

(7)获取队头元素,直接返回队头下标的位置的数据即可

(8)获取队尾元素,返回 (rear-1+k+1)%(k+1) 位置的数据即可,也可以判断rear是不是在0的位置,在的话top=k,不在0的位置的话就top=rear-1
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/fad58d936d8b45a0b6b65024f18fd026.png

4、代码实现:

//队列结构体
typedef struct {
    //储存数据
    int *arr;
    //头
    int front;
    //指向尾的下一个
    int rear;
    //大小
    int k;
} MyCircularQueue;

//初始化循环队列
MyCircularQueue* myCircularQueueCreate(int k) {
    //队列
     MyCircularQueue* obj=( MyCircularQueue*)malloc(sizeof(MyCircularQueue));

     //初始化成员
     obj->arr=(int*)malloc(sizeof(int)*(k+1));
     obj->front=0;
     obj->rear=0;
     obj->k=k;
     
     return obj;
}

//是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    //当队头的下标等于队尾的下标时队列为空
    return obj->front==obj->rear;
}

//是否为满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    //当队头的下标等于队尾加一模上k+1时队列满了
    return obj->front==(obj->rear+1)%(obj->k+1);
}

//入队
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //当队列满了就返回false
        if(myCircularQueueIsFull(obj))
           return false;

    //放到rear位置上
        obj->arr[obj->rear]=value;
    //这样当rear+1==k+1时,让rear回到0这个位置上
        obj->rear=(obj->rear+1)%(obj->k+1);

           return true;
}

//出队
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //空时返回false
    if(myCircularQueueIsEmpty(obj))
       return false;
      //队头下标加1,莫上k+1当front+1==k+1时能回到0那个位置
     obj->front=(obj->front+1)%(obj->k+1);

     return true;
}

//查看头元素
int myCircularQueueFront(MyCircularQueue* obj) {
     //空时返回-1
    if(myCircularQueueIsEmpty(obj))
      return -1;

     //直接展示front位置即可
      int tmp=obj->arr[obj->front];

      return tmp;
}

//查看队尾元素
int myCircularQueueRear(MyCircularQueue* obj) {
    //空时返回-1
    if(myCircularQueueIsEmpty(obj))
      return -1;
    //因为返回的是rear-1位置上的数据,当rear>0时,查看的位置时rear-1,当rear=0时就是查看k位置的数据了
      int tmp=obj->arr[(obj->rear-1+obj->k+1)%(obj->k+1)];

      return tmp;
    
}

//释放
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->arr);
    free(obj);
}

循环双端队列

1、循环双端队列就是在循环队列的基础上增加了一些接口,如:可以进行队头的插入,进行尾部的删除。

2、实现的功能接口:

实现 MyCircularDeque 类:

(1)MyCircularDeque(int k) :构造函数,双端队列最大为 k 。

(2)boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。

(3)boolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 false 。

(4)boolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 false 。

(5)boolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 false 。

(6)int getFront() ):从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。

(7)int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1 。
(8) boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false 。

(9)boolean isFull() :若双端队列满了,则返回 true ,否则返回 false 。

3、设计
(1)用双向链表的节点,这样方便找到尾部的上一个节点,利于队尾的删除。
(2)定义size来判断空和满,再定义两个节点指针,分别指向队头(front)队尾(rear)容量(k)前驱指针(next)后驱指针(next1)
(3)判断为空,当size=0时为空。
(4)判断是否满,当size=k时为满。
(5)队头插入数据,申请一个节点tmp,再将tmp和front连起来,最后front=tmp即可

在这里插入图片描述

(6)队尾插入数据,申请一个节点tmp,再将tmp和rear连接起来,最后rear=tmp即可
在这里插入图片描述

(7)队头删除,先保存队头的后一个节点next,再将front释放,最后将front=next并把front->next1=NULL即可,注意顺序不能乱。

在这里插入图片描述

(8)队尾删除,先保存前一个节点next1,再将rear释放,最后将rear=next1并把rear->next=NULL即可,注意顺序不能乱。

在这里插入图片描述

(9)获取队头元素,直接返回front的数据即可。
(10)获取队尾元素,直接返回rear的数据即可。

4、代码实现:

//双向链表的结构体
typedef struct  ls
{
     //前驱
   struct ls *next;
   //后驱
   struct ls *next1;
   //数据
   int val;
}ls;

class MyCircularDeque {
public:
     //初始化
    MyCircularDeque(int k) {
    //容量
         this->k=k;
      //大小
         this->size=0;
         this->rear=NULL;
         this->front=NULL;
    }
    
    //队头插入数据
    bool insertFront(int value) {
    //  满了,就返回
           if(isFull())
             return false;

      //没满
      //申请一个节点
             ls *tmp(ls*)malloc(sizeof(ls));
             tmp->next=NULL;
             tmp->next1=NULL;
             tmp->val=value;

       //空的话头和尾指向第一个节点
             if(front==NULL)
             {
               front=rear=tmp;
             }
             //不空,插入头
             else
             {
                 front->next1=tmp;
                 tmp->next=front;
                 front=tmp;
             }
             
          //大小加1
             size++;

            return true;
    }
    
    //队尾插入数据
    bool insertLast(int value) {
              if(isFull())
             return false;

      //申请节点
             ls *tmp=(ls*)malloc(sizeof(ls));
             tmp->next=NULL;
             tmp->next1=NULL;
             tmp->val=value;
             
             if(rear==NULL)
             {
                 front=rear=tmp;
             }
             //尾插到rear后面
             else
             {
                   tmp->next1=rear;
                   rear->next=tmp;
                   rear=tmp;
             }
             
     //大小加1
             size++;

             return true;
    }
    
 //删队头   
    bool deleteFront() {
    //为空
        if(isEmpty())
         return false;
         
         //只有一个元素
         ls *tmp=front->next;
         free(front);
         if(tmp==NULL)
           front=rear=tmp;
           //多个元素
         else
         {
        front=tmp;
        front->next1=NULL;
         }
       
       //大小-1     
         size--;

          return true;
    }
    
    //删队尾
    bool deleteLast() {
          if(isEmpty())
         return false;
         
         //只有一个元素
         ls *tmp=rear->next1;
         free(rear);

         if(tmp==NULL)
         {
             rear=front=tmp;
         }
         else
         {
             tmp->next=NULL;
             rear=tmp;
         }
    // 大小-1
         size--;

          return true;
    }
    
    //显示头元素
    int getFront() {
    //为空
          if(isEmpty())
         return -1;

//直接返回头节点的数据
         return front->val;
    }
    
    //显示尾节点元素
    int getRear() {
    //为空
        if(isEmpty())
         return -1;
         
//直接返回尾节点数据
         return rear->val;

    }
    
    //判断是否为空
    bool isEmpty() {
    //当size==0是为空
       return size==0;
    }
    
    //判断是否为满
    bool isFull() {
    //size==k就满了
      return size==k;
    }
    
//释放链表
    ~MyCircularDeque()
    {
        ls* tmp=front;
        while(tmp)
        {
            ls*p=tmp->next;
            free(tmp);
            tmp=p;
        }
    }
    //头和尾
    ls* front;
    ls* rear;
    //容量和大小
    int k;
    int size;
};

以上就是我的分享了

最后,感谢大家的观看!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024高频前端面试题 HTML 和 CSS 篇

JS和ES6 篇: ​​​​​​​2024高频前端面试题 JavaScript 和 ES6 篇-CSDN博客 一 . HTML 篇 1. H5有什么新特性 1) 语义化标签 用正确的标签做正确的事情。 html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析&…

Springboot实现缓存预热

很多时候我们代码中使用缓存时都是先判断缓存中没有数据我们再读取数据库而有则直接使用缓存数据,而在系统冷启动(当系统重启或新启动时,缓存是空的,这被称为冷启动)时,我们毫无意外都是直接获取数据库的内容,这时候缓…

Pytorch Geometric 将表格数据集(CSV 文件)转换为图形数据集

导 读 如今图数据集正在以惊人的速度出现,所有化学分子、社交网络和推荐系统主要以图数据结构的形式存储数据 有需要的朋友关注公众号【小Z的科研日常】,获取更多内容。 01、如何转换CSV文件至图形数据结构 确定图形数据所需的基本信息 节点(…

ViT的若干细节

之前只看了ViT的大概结构,具体的模型细节和代码实现知之甚少。随着ViT逐渐成为CV领域的backbone,有必要重新审视下。 patch -> token 为了将图片处理成序列格式,很自然地想到将图片分割成一个个patch,再把patch处理成token。 …

Go-知识struct

Go-知识struct 1. struct 的定义1.1 定义字段1.2 定义方法 2. struct的复用3. 方法受体4. 字段标签4.1 Tag是Struct的一部分4.2 Tag 的约定4.3 Tag 的获取 githupio地址:https://a18792721831.github.io/ 1. struct 的定义 Go 语言的struct与Java中的class类似&am…

数据结构c版(2)——二叉树

本章我们来了解一下二叉树这一概念。 目录 1.树概念及结构 1.1树的概念​​​​​​​ 1.2 树的特点: 1.3 树的相关概念 1.4 树的表示​​​​​​​ 1.5 树在实际中的运用(表示文件系统的目录树结构) 2.二叉树概念及结构 2.1概念 …

华为云命令行工具KooCLI—高效云端管理的秘诀

做运维多年,公司从传统运维改为云上。刚一接触时,确实因为要学习很多云知识而烦恼。每次想要执行某个操作时,都要先登录到云平台,浏览界面,寻找正确的按钮。这样不仅浪费时间,还经常出错。直到有一天&#…

【深度学习笔记】计算机视觉——锚框

锚框 目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边界从而更准确地预测目标的真实边界框(ground-truth bounding box)。 不同的模型使用的区域采样方法可能不同。 这里…

STM32F103ZET6移植FreeRTOS

FreeRTOS是一款免费开源的轻量级操作系统 一、获取源码 方式一、官网:www.freertos.org 方式二(推荐)、托管网址: FreeRTOS Real Time Kernel (RTOS) - Browse /FreeRTOS at SourceForge.net 找到对应的版本直接下载.ZIP文件…

2023年09月CCF-GESP编程能力等级认证Scratch图形化编程三级真题解析

本文收录于专栏《Scratch等级认证CCF-GESP真题解析》,专栏总目录・点这里 一、单选题(共15题,共30分) 第1题 我国第一台大型通用电子计算机使用的逻辑部件是( )。 A:集成电路 B:大规模集成电路 C:晶体管 D:电子管 答案:D 第2题 下列流程图的输出结果是?( ) …

【自然语言处理】BitNet b1.58:1bit LLM时代

论文地址:https://arxiv.org/pdf/2402.17764.pdf 相关博客 【自然语言处理】BitNet b1.58:1bit LLM时代 【自然语言处理】【长文本处理】RMT:能处理长度超过一百万token的Transformer 【自然语言处理】【大模型】MPT模型结构源码解析(单机版)…

排序(1)——直接插入排序+冒泡排序

目录 1 排序的概念及其应用 1.1 排序的概念 1.2 排序的应用 1.3 常见的排序算法 2 直接插入排序 2.1 基本思想 2.2 基本思路 2.3 代码实现 2.4 时间复杂度 3 冒泡排序(回顾) 3.1 思路分析 3.2 时间复杂度 4 比较 1 排序的概念及其应用 1.…

STM32 (1)

1.基本信息 stm32是由ST公司生产的一种32位微控制器(单片机)。 1.1 各种型号 stm32是32位单片机的总称,有多种不同的系列。 32即用32个比特位表示一个地址,寻址范围:0x00000000 --0xffffffff (4GB) 1.2 存储密度 …

「优选算法刷题」:在每个树行中找最大值

一、题目 给定一棵二叉树的根节点 root &#xff0c;请找出该二叉树中每一层的最大值。 示例1&#xff1a; 输入: root [1,3,2,5,3,null,9] 输出: [1,3,9]示例2&#xff1a; 输入: root [1,2,3] 输出: [1,3]提示&#xff1a; 二叉树的节点个数的范围是 [0,104]-231 < N…

Flink:Temporal Table Function(时态表函数)和 Temporal Join

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

第十四届蓝桥杯大赛B组 JAVA 蜗牛 (递归剪枝)

题目描述&#xff1a; 这天&#xff0c;一只蜗牛来到了二维坐标系的原点。 在 x 轴上长有 n 根竹竿。它们平行于 y 轴&#xff0c;底部纵坐标为 0&#xff0c;横坐标分别为 x1, x2, …, xn。竹竿的高度均为无限高&#xff0c;宽度可忽略。蜗牛想要从原点走到第 n 个竹竿的底部也…

Ubuntu20.04使用XRDP安装原生远程桌面

Ubuntu20.04使用XRDP安装原生远程桌面 1.安装gnome桌面 # 如果没有更新过源缓存&#xff0c;先更新一下 sudo apt update# 安装gnome桌面 # 可选参数 --no-install-recommends&#xff0c;不安装推荐组件&#xff0c;减少安装时间和空间占用 sudo apt install ubuntu-desktop…

Docker基础教程 - 1 Docker简介

更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 1 Docker简介 Docker是一个强大的容器化平台&#xff0c;让你能够更轻松地构建、部署和运行应用程序。 下面我们来学习 Docker。 1.1 Docker是什么 1 现在遇到的问题 每次部署一台服务器&…

Apache JMeter 5.6.3 安装

源码下载 curl -O https://dlcdn.apache.org//jmeter/source/apache-jmeter-5.6.3_src.zipJMeter 下载 curl -O https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.3.zipjmeter.properties 里 设置中文 windows系统上解压&#xff0c;双击jmeter.bat 启动 执行参…

618快递准点到达,别忘了感谢它!

进入6月以来&#xff0c;全国快递日均业务量飞速上涨。 虽然618大促是电商的主场&#xff0c;但作为不可或缺的物流环节&#xff0c;为了这场年中大考&#xff0c;快递企业在此期间也使尽浑身解数&#xff0c;竞相比拼配送速度。那么&#xff0c;为了更快的时效&#xff0c;快递…