首页 > 其他分享 >【数据结构】队列详解和模拟实现

【数据结构】队列详解和模拟实现

时间:2024-07-24 12:28:18浏览次数:15  
标签:Head null ListNode val 队列 Tail 详解 数据结构

大家好,今天我们学习队列,本篇博客主要涉及一般队列,环形队列和双端队列,每个队列应用场景均有所差异,下面我们一起来看看吧。

队列(Queue)

一,概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特性
入队列:进行插入操作的一端称为队尾(Tail/Rear)

出队列:进行删除操作的一端称为队头(Head/Front)

队列的概念其实很好理解,想象成排队即可,先来的元素可以先出队列

二,队列的使用

1.队列实质

在Java中,Queue是个接口,底层是通过链表实现的。

2.常用方法:

boolean offer(E e) :                                 入队列
E poll() :                                                   出队列
peek() :                                                     获取队头元素
int size():                                                  获取队列中有效元素个数
boolean isEmpty() :                                检测队列是否为空

需要注意的是, Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

3.应用:

import java.util.LinkedList;
import java.util.Queue;
public class Main {
    public static void main(String[] args) {
        Queue<Integer> q = new LinkedList<>();
        q.offer(1);
        q.offer(2);
        q.offer(3);
        q.offer(4);// 从队尾入队
        System.out.println(q.size());
        System.out.println(q.peek()); // 获取队头元素
        q.poll();
        System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回
        if (q.isEmpty()) {
            System.out.println("队列空");
        } else {
            System.out.println(q.size());
        }
    }
}

三:队列的模拟实现

1.事前准备

已经说过Java原生队列底层是双向链表,因此我们采用双向链表实现队列,当然,使用单链表也能达成目的,但是并没有双链表方便

首先我们创建一个自己的队列并定义好节点和头尾节点

public class MyQueue {
    class ListNode{
        int val;
        ListNode next;
        ListNode prev;
        ListNode(int val){
            this.val=val;
        }
    }
    ListNode Head= null;
    ListNode Tail= null;
    int size=0;
}

2.成员方法

a.入队

我们选择在双链表尾部进行插入即可,和我们在双链表写过的尾插方法一样

public void offer(int val){
        ListNode node=new ListNode(val);
        if(Head==null&&Tail==null){
            Head=Tail=node;
        }else {
            Tail.next=node;
            node.prev=Tail;
            Tail=node;
        }
        size++;
    }

b,出队

出队列与双向链表头删方法一致,分三种情况

1. 队列为空
 2. 队列中只有一个元素----链表中只有一个节点---直接删除
 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除

public int poll() {
        int val = -1;
        if (Head == null) {
            return -1;
        } else if (Head == Tail) {
            val=Head.val;
            Head = null;
            Tail = null;
        } else {
            val=Head.val;
            ListNode tmp=Head.next;
            Head.next.prev = null;
            Head.next = null;
            Head=tmp;
        }
        size--;
        return val;
    }

c,获取头部元素

和删除非常像,但是不执行删除操作,返回头部val值

public int peek() {
        if (Head == null) {
            return -1;
        }
        return Head.val;
    }

d,判空

主要与size有关,或者判断头节点是否为空

public boolean isEmpty(){
return Head == null;
//return size==0;
}

我们可以测试一下我们自己的队列,是完全没问题的

public class MyQueue {
    class ListNode {
        int val;
        ListNode next;
        ListNode prev;

        ListNode(int val) {
            this.val = val;
        }
    }
    private  ListNode Head = null;
    private ListNode Tail = null;
    private int size = 0;

    public void offer(int val) {
        ListNode node = new ListNode(val);
        if (Head == null && Tail == null) {
            Head = Tail = node;
        } else {
            Tail.next = node;
            node.prev = Tail;
            Tail = node;
        }
        size++;
    }
    public int poll() {
        int val = -1;
        if (Head == null) {
            return -1;
        } else if (Head == Tail) {
            Head = null;
            Tail = null;
        } else {
            val = Head.val;
            ListNode tmp = Head.next;
            Head.next.prev = null;
            Head.next = null;
            Head = tmp;
        }
        size--;
        return val;
    }

    public int peek() {
        if (Head == null) {
            return -1;
        }
        return Head.val;
    }

    public boolean isEmpty() {
        return Head == null;
        //return size==0;
    }
}

四,循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。循环形队列通常使用数组实现

当然,为了让他循环并且不至于空间浪费,这里有几个小技巧

1. 下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length

2. 下标最前再往前(offset 小于 array.length): index = (index + array.length - offset) % array.length

这里只作简介,感兴趣的可以看看下面这道设计循环队列的OJ

. - 力扣(LeetCode)

双端队列 (Deque)

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,此队列元素可以从队头出队和入队,也可以从队尾出队和入队。




Deque是一个接口,使用时必须创建LinkedList的对象。

在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用该接口。

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

好啦,本期博客到此结束,感谢大家观看。

标签:Head,null,ListNode,val,队列,Tail,详解,数据结构
From: https://blog.csdn.net/2302_81982408/article/details/140655417

相关文章

  • 数据结构实验二——单链表的基本操作(2021级zzu)
    ps:滴~打卡第二天,好困啊~~~~~~数据结构实验二——单链表的基本操作一、实验目的二、实验内容(选其中之一写实验报告)三、问题描述四、数据结构定义五、算法思想及算法设计5.1实验内容(1)5.1.1理论实现和代码实现5.2实验内容(2)5.2.1代码实现六、运行示例七、实验代......
  • GitHub 详解教程
    1.引言GitHub是一个用于版本控制和协作的代码托管平台,基于Git构建。它提供了强大的功能,使开发者可以轻松管理代码、追踪问题、进行代码审查和协作开发。2.Git与GitHub的区别Git是一个分布式版本控制系统,用于跟踪文件的更改历史。GitHub是一个基于Git的在线平台,......
  • [杂项] [算法] [数据结构] 暑期专题狂补
    或曰,有学长两天授吾以十专题,吾顿感日月之紧迫,以专题竟不能以吾之所有,遂成此文,以记之语文确实没学好本文可能涵盖多个知识点,故每个的讲解比较简略,仅供参考一.2-SAT$2-SAT$用于求解一个变量只有两种情况的适应性问题(就是有没有解以及输出一种方案);其实可以类比二分图最大......
  • 在 Kubernetes 中设置 Pod 优先级及其调度策略详解
    个人名片......
  • Kubernetes Secret 详解
    KubernetesSecret是一种用于存储和管理敏感信息的对象,如密码、OAuth令牌和SSH密钥等。使用Secret可以避免将机密数据直接放在Pod规约或容器镜像中,从而增加了应用程序的安全性。Secret的类型Kubernetes支持多种类型的Secret,包括:​​Opaque​​:默认的Secret类......
  • 【数据结构与算法—基础篇1】
    1、基础知识1、数据结构三要素:逻辑结构、存储结构、数据的运算;其中逻辑结构包括线性结构(线性表、栈、队列)和非线性结构(树、图、集合)2、数据是信息的载体,是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。3、数据元素是数据的基本......
  • SpringBoot整合SSE技术详解
    SpringBoot整合SSE技术详解1.引言在现代Web应用中,实时通信变得越来越重要。Server-SentEvents(SSE)是一种允许服务器向客户端推送数据的技术,为实现实时更新提供了一种简单而有效的方法。本文将详细介绍如何在SpringBoot中整合SSE,并探讨SSE与WebSocket的区别。2.SS......
  • Java之this关键字详解
    this关键字在类中的普通成员方法中,可以使用this关键字,其表示调用当前方法的对象引用,即哪个对象调用该方法,this就代表哪一个对象。this关键字用法:对成员变量和局部变量进行区分固定格式:this.数据成员;调用类中的成员方法固定格式:this.成员方法(实际参数列表);调用......
  • redis原理之底层数据结构-跳表
    1.什么是跳表1.1链表及其不足链表是在程序设计中最常见的数据结构之一,它通过指针将多个链表节点连接起来,这样就可以将逻辑上同一类的数据存储到不连续的内存空间上。链表结构如下:但是链表有一个问题,就是当链表需要查询一个元素的时候,需要从链表头部开始遍历,时间复杂度为o(......
  • 一文详解Type C-CC引脚的作用
    一文详解TypeC-CC引脚的作用关于USBCC引脚的功能,想必很多人都很好奇。USB经常接触,其内部的VBUSD+与D-大家肯定都知道了解,但对于CC引脚的存在却很少有人知道其作用。所以呢,今日,小白就来简单的介绍一下其功能。首先还是要先介绍几个关键名词:DFP(DownstreamFacingPort)下行端口......