数据结构-循环队列和循环双端队列的多角度实现

news2024/11/17 14:51:14

文章目录

      • 1. 循环队列的数组形式实现
      • 2. 循环队列的链表实现
      • 3. 循环双端队列的数组形式实现
      • 4. 循环双端队列的链表实现

在力扣的题面如下
在这里插入图片描述
在这里插入图片描述

1. 循环队列的数组形式实现

其实循环队列的数组形式只有下面要注意的点,只要掌握了下面的这几点,代码层面上就没有什么问题了

用数组模拟的思路跟循环单向队列是完全一致的,要记住下面的几个点

  • 1 . first 指向的是头元素的下标 , last 指向的是尾元素的下一个位置的下标
  • 2 . 在申请数组空间的时候要多申请一个空间的目的是,讲判断空与判断满的条件区分开
  • 判断空就是 first == last 判断满就是 "first的下一个" == last;
    
  • 3 . 在循环队列里面,如何++,如何–?
  • ++ : (first + 1) % len  ;  (last + 1) % len;
    
  • -- : (first - 1 + len) % len  ;  (last - 1 + len) % len
    
  • 4 . 元素的个数 size == (last - fist + len) % len;

下面是数组形式的实现代码

class MyCircularQueue {
    int[] elementData;
    int first;
    int last;

    public MyCircularQueue(int k) {
        elementData = new int[k + 1];
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        elementData[last] = value;
        last = (last + 1)%  elementData.length;
        return true;
    }
    
    public boolean deQueue() {
         if(isEmpty()){
             return false;
         }
         first = (first + 1)%elementData.length;
         return true;
    }
    
    public int Front() {
         if(isEmpty()){
             return -1;
         }
         return elementData[first];
    }
    
    public int Rear() {
         if(isEmpty()){
             return  -1;
         }
         int index = last == 0 ? elementData.length - 1 : last -1;
         return elementData[index];
    }
    
    public boolean isEmpty() {
        return last == first;
    }
    
    public boolean isFull() {
         return first == (last + 1)  % elementData.length;
    }
}

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue obj = new MyCircularQueue(k);
 * boolean param_1 = obj.enQueue(value);
 * boolean param_2 = obj.deQueue();
 * int param_3 = obj.Front();
 * int param_4 = obj.Rear();
 * boolean param_5 = obj.isEmpty();
 * boolean param_6 = obj.isFull();
 */

2. 循环队列的链表实现

鉴于单链表的尾巴节点每次都要寻找,所以为了简便,我们采用双向链表进行模拟,注意,这里我们对于链表节点的定义就是我们LinkedList中的源码形式,有空可以去看看我们LinkedList的底层源码,这里其实就是多了个size来标记我们的链表节点数量
代码实现如下


/**
 * 尝试用双向链表来模拟循环队列
 */
public class CircleQueue {


    /**
     * 下面是根据原代码模拟的定义的节点类
     * @param <T>
     */
    static class Node<T> {
        public T item;
        public Node<T> prev;
        public Node<T> next;

        public Node (Node<T> prev,T item,Node<T> next) {
            this.prev = prev;
            this.item = item;
            this.next = next;
        }
    }

    /**
     * 下面是所需要的基本结构
     */
    private Node first;
    private Node last;
    private int size;
    private int capacity;


    public CircleQueue(int k) {
        this.size = 0;
        first = last = null;
        capacity = k;
    }

    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }

        Node<Integer> node = new Node<>(null,value,null);
        if(first == null && last == null){
            first = node;
            last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
        this.size++;
        return true;
    }

    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }

        if(last == first){
            last = first = null;
        }else{
            first = first.next;
            first.prev.next = null;
            first.prev.item = null;
        }
        this.size--;
        return true;
    }

    public int Front() {
        if(isEmpty()){
            return -1;
        }
        return (int)first.item;
    }

    public int Rear() {
        if(isEmpty()){
            return -1;
        }

        return (int)last.item;
    }

    public boolean isEmpty() {
        return first == null && last == null;
    }

    public boolean isFull() {
        return this.size == this.capacity;
    }
}

3. 循环双端队列的数组形式实现

用数组实现队列源码层面是我们的ArrayDeque这个类完成的,这里不再多说了,和我们的1.用数组实现循环队列是一致的

/**
 * 首先尝试是数组来模拟循环双端队列
 * 其次我们再用双向链表来尝试模拟一下循环双端队列
 * 用数组模拟的思路跟循环单向队列是完全一致的,要记住下面的几个点
 * 1 . first 指向的是头元素的下标 , last 指向的是尾元素的下一个位置的下标
 * 2 . 在申请数组空间的时候要多申请一个空间的目的是,讲判断空与判断满的条件区分开
 *     判断空就是 first == last 判断满就是 "first的下一个" == last;
 * 3 . 在循环队列里面,如何++,如何--?
 *     ++ : (first + 1) % len  ;  (last + 1) % len;
 *     -- : (first - 1 + len) % len  ;  (last - 1 + len) % len
 * 4 . size == (last - fist + len) % len;
 */
class MyCircularDeque {

    int[] elementData;
    int first;
    int last;

    public MyCircularDeque(int k) {
        elementData = new int[k + 1];
        first = last = 0;
    }

    public boolean insertFront(int value) {
        if(isFull()){
            return false;
        }

        first = (first - 1 + elementData.length) % elementData.length;
        elementData[first] = value;
        return true;
    }

    public boolean insertLast(int value) {
        if(isFull()){
            return false;
        }

        elementData[last] = value;
        last = (last + 1) % elementData.length;
        return true;
    }

    public boolean deleteFront() {
        if(isEmpty()){
            return false;
        }

        first = (first + 1) % elementData.length;
        return true;
    }

    public boolean deleteLast() {
        if(isEmpty()){
            return false;
        }

        last = (last - 1 + elementData.length) % elementData.length;
        return true;
    }

    public int getFront() {
        if(isEmpty()){
            return -1;
        }

        return elementData[first];
    }

    public int getRear() {
        if(isEmpty()){
            return -1;
        }

        return elementData[(last - 1 + elementData.length) % elementData.length];
    }

    public boolean isEmpty() {
        return first == last;
    }

    public boolean isFull() {
        return (last + 1) % elementData.length == first;
    }
}

4. 循环双端队列的链表实现

其实就是比2.多了一个addFirst,和 removeLast
代码实现如下


/**
 * 下面我们尝试使用双向链表来模拟我们的循环双端队列
 */
class MyCircularDequeUseLinkedList {
    static class Node<T> {
        Node<T> prev;
        T item;
        Node<T> next;

        public Node(Node<T> prev,T item,Node<T> next){
            this.prev = prev;
            this.item = item;
            this.next = next;
        }
    }
    private int size;
    private int capacity;
    private Node first;
    private Node last;

    public MyCircularDequeUseLinkedList(int k) {
        this.size = 0;
        last = first = null;
        this.capacity = k;
    }

    public boolean insertFront(int value) {
        if(isFull()){
            return false;
        }

        Node<Integer> node = new Node<>(null,value,null);
        if(isEmpty()){
            first = last = node;
        }else{
            node.next = first;
            first.prev = node;
            first = node;
        }
        size++;
        return true;
    }

    public boolean insertLast(int value) {
        if(isFull()){
            return false;
        }

        Node<Integer> node = new Node<>(null,value,null);
        if(isEmpty()){
            first = last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = node;
        }
        size++;
        return true;
    }

    public boolean deleteFront() {
        if(isEmpty()){
            return false;
        }

        if(first == last){
            last = first = null;
        }else{
            first = first.next;
            first.prev.next = null;
            first.prev.item = null;
            first.prev = null;
        }
        size--;
        return true;
    }

    public boolean deleteLast() {
        if(isEmpty()){
            return false;
        }

        if(last == first){
            first = last = null;
        }else{
            last = last.prev;
            last.next.prev = null;
            last.next.item = null;
            last.next = null;
        }
        size--;
        return true;
    }

    public int getFront() {
        if(isEmpty()){
            return -1;
        }
        return (int)first.item;
    }

    public int getRear() {
        if(isEmpty()){
            return -1;
        }
        return (int)last.item;
    }

    public boolean isEmpty() {
        return first == null && last == null;
    }

    public boolean isFull() {
        return this.size == this.capacity;
    }
}

为什么不用单链表实现的原因其实是单链表每次想尾插都要走到最后一个位置,时间复杂度太高,有兴趣的话也可以自己模拟一下试试

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

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

相关文章

精灵传信系统/支持对接易支付/网站+小程序双端php源码下载

简介 精灵传信支持在线提交发送短信&#xff0c;查看回复短信&#xff0c;在线购买额度&#xff0c;自定义对接易支付&#xff0c;设置违禁词&#xff0c;支持网站小程序双端。&#xff08;文末下载&#xff09; 演示截图 在数字化浪潮的推动下&#xff0c;技术创新正以前所未…

VUE 弹框内容懒加载-真实项目

背景&#xff1a;VUE 页面&#xff0c;点击按钮&#xff0c;弹框&#xff0c;内容从接口获取&#xff0c;数据量比较大&#xff0c;鼠标滑到页面最底部&#xff0c;调取一次接口&#xff0c;分批加载&#xff1b; demo&#xff1a; <template><div><!-- 触发弹…

通用变频器ACS800-04M-0320-3可议价

商业别名&#xff1a;ACS800-04M-0320-3 产品编号&#xff1a;68279429 ABB 型号名称&#xff1a;ACS800-04M-0320-3 目录说明&#xff1a;ACS800-04M-0320-3&#xff1b; ACS800-04M-0320-3 Pcont.max:250kW, Icont.max:521A 原产地&#xff1a;芬兰 (FI) 海关税则号&#xf…

现代图形API综合比较:Vulkan | DirectX | Metal | WebGPU

Vulkan、DirectX、Metal 和 WebGPU 等低级图形 API 正在融合为类似于当前 GPU 构建方式的模型。 图形处理单元 (GPU) 是异步计算单元&#xff0c;可以处理大量数据&#xff0c;例如复杂的网格几何形状、图像纹理、输出帧缓冲区、变换矩阵或你想要计算的任何数据。 NSDT工具推荐…

springboot3 集成knife4j No endpoint GET /doc.html.

springboot3 集成knife4j 访问页面&#xff1a;http://127.0.0.1:8022/doc.html 提示&#xff1a; No endpoint GET /doc.html. 描述环境&#xff1a; java17 springboot3.2.0 knife4j的jar包 <dependency><groupId>com.github.xiaoymin</groupId><a…

vue实现周日历 日历按周切换 vue日程管理

实现的功能 1、点击今天&#xff1a;回到今日日期并选中今日日期&#xff0c;查当天数据 2、点击左箭头&#xff1a;切换上一周 3、点击右箭头&#xff1a;切换下一周 4、黄圆圈代表有日程提醒&#xff0c;点击选中&#xff0c;下方对应显示当前日程提醒的内容&#xff0c;没有…

打造稳定安全的亚马逊测评环境:关键步骤与要点一览

亚马逊测评环境的搭建是一项既复杂又需要深入细致考虑的工作&#xff0c;它涉及多方面的技术配置和资源准备。以下是一些关键步骤和要点&#xff0c;帮助您更高效地构建测评环境。 一、资源筹备 1. 养号系统&#xff1a;选择稳定、高效的养号系统&#xff0c;确保能够模拟真实…

上传文件到HDFS

1.创建文件夹 hdfs -dfs -mkdir -p /opt/mydoc 2.查看创建的文件夹 hdfs -dfs -ls /opt 注意改文件夹是创建在hdfs中的&#xff0c;不是本地&#xff0c;查看本地/opt&#xff0c;并没有该文件夹。 3.上传文件 hdfs dfs -put -f file:///usr/local/testspark.txt hdfs://m…

【JavaEE初阶系列】——网络原理之进一步了解应用层以及传输层的UDP协议

目录 &#x1f6a9;进一步讲应用层 &#x1f388;自定义应用层协议 &#x1f388;用什么格式组织 &#x1f469;&#x1f3fb;‍&#x1f4bb;xml(远古的数据组织格式) &#x1f469;&#x1f3fb;‍&#x1f4bb;json(当下最流行得一种数据组织格式) &#x1f469;&…

Docker(二)Docker+ server部署极简前端页面

本篇文章介绍如何使用 Dockerserver 将一个极简前端页面进行部署 1.本地运行一个简单的前端页面&#xff0c;再把它部署到服务器上 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&quo…

算法思想总结:栈

一、栈的经典应用&#xff1a;波兰表达式与逆波兰表达式 我们平时看到的 12*&#xff08;3-4*5&#xff09;6/7 叫做中缀表达式&#xff0c;平时我们习惯用这个计算的原因是我们可以整体地去看到这个表达式并且清楚地知道各个运算符的优先级&#xff0c;但是计算机并不一定知道…

JavaScript之模块化规范详解

文章的更新路线&#xff1a;JavaScript基础知识-Vue2基础知识-Vue3基础知识-TypeScript基础知识-网络基础知识-浏览器基础知识-项目优化知识-项目实战经验-前端温习题&#xff08;HTML基础知识和CSS基础知识已经更新完毕&#xff09; 正文 CommonJS、UMD、CMD和ES6是不同的模块…

详解爬虫基本知识及入门案列(爬取豆瓣电影《热辣滚烫》的短评 详细讲解代码实现)

目录 前言什么是爬虫&#xff1f; 爬虫与反爬虫基础知识 一、网页基础知识 二、网络传输协议 HTTP&#xff08;HyperText Transfer Protocol&#xff09;和HTTPS&#xff08;HTTP Secure&#xff09;请求过程的原理&#xff1f; 三、Session和Cookies Session Cookies Session与…

核桃派全志H616实现VNC远程桌面教程

VNC远程桌面 核桃派预装了VNC服务器&#xff0c;VNC适应于局域网&#xff08;通常指同一个路由器网络下&#xff09;桌面登录。使用该服务前先确保核桃派已经通过以太网或无线WiFi连接到路由器。 使用核桃派桌面系统的时候由于要配置各类信息和联网&#xff0c;可以使用HDMI显…

【C语言】每日一题,快速提升(5)!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. strlen函数 2. strcpy函数 3. strcat函数 题目&#xff1a;模拟实现 strlen--strcpy--strcat--三个函数 1. strlen函数 字符串计算 #include <stdio.h…

硕士博士学位论文格式检查规范

包含标题、摘要、英文缩写、关键词、公式、表格、图片、参考文献&#xff0c;只能说太强了 学位论文检查三十六策点击蓝字 关注我们 写在前面 同学们撰写学位论文时&#xff0c;常常犯一些错误&#xff0c;既有格式错误&#xff0c;也有内容错误。本文列举36https://mp.weixin.…

【python】如何通过python来发送短信

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

SFP、SFP+、SFP28 与 QSFP28 收发器之间的差异:兼容性和性能

近年来&#xff0c;网络技术发展迅速&#xff0c;因此&#xff0c;计算专业人员面临着越来越令人困惑的术语和缩写词。 管理数据中心时必须了解的一个关键领域是收发器&#xff0c;特别是 SFP (1550nm/1310nm)、SFP (850nm) 和 QSFP28 (4x25G) 之间的差异。 这些型号在兼容性方…

【热门话题】常用经典目标检测算法概述

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 常用经典目标检测算法概述1. 滑动窗口与特征提取2. Region-based方法R-CNN系列M…

【日志】CSDN-AI助手升级日志

CSDN-AI助手升级日志 2023/04/05上线 支持点赞、收藏回访 关注回访&#xff08;对方至少有一条博客的记录&#xff09; 评论回访 私信检测到群发消息自动三连 OR 通过私信指令三连触发 bug优化 优化检测模式&#xff0c;防止出现多触发情况 为了防止操作额度不够&#xff0c…