队列的定义与实现

简介: 前面一章讲了栈的定义与实现,我们一样可以通过限制线性表的一些基本操作来实现另一种常用的数据结构---队列,这一章简单来讲讲队列的定义与实现。


一、定义



队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表,进行插入操作的一端称为队尾(rear),进行删除的一端为队头(front),插入数据元素的操作叫做入队,删除数据元素的操作叫做出队,它具有先进先出(First In First Out,FIFO)的特性。

微信图片15.png

二、队列的基本操作分析



前面章节说到,线性表可以通过顺序存储和链式存储来实现,作为操作受限的线性表也一样,所以后面也会通过两种存储结构来分析队列的基本操作实现。

在顺序存储结构中,一般会使用数组来实现,定义一个队列,约定使用 front 来存放队头元素的位置,使用 rear 来存放队尾的位置,当 front=rear=-1 时表示队列为空,入队和出队都是通过移动 rearfront 指针来实现,如下图所示,当 a9 入队后不能再做入队操作,而实际上空间并没有占满,此时会出现假溢出现象,为了避免这种情况,我们可以把该连续空间视为“循环顺序队列”。

微信图片17.png在循环顺序队列中,当 a9 入队后再做入队操作时,会将数据元素存储在数组前面出队后的空闲空间中,这样数据元素在数组中就会形成一个循环的队列,在这种情况下,当队满或者空队时都会存在 front=rear ,所以要通过 size 来判断队列是空还是满,当 size=array.length 时队满,当 size=0 时队空。使用循环队列时,队头和队尾的位置变换实现如下:

 
         

微信图片14.png在链式存储结构中,可以直接使用单向链表来实现队列,此时,我们把链表的头部作为队头,把链表的尾部作为队尾,也就是说,在链表尾部插入,链表头部删除,在代码实现中,需要定义两个指针 frontrear 分别指向链表的第1个结点和最后1个结点。

微信图片13.png

1. 入队


在顺序存储中进行入队操作,只需要通过 rear 来定位队尾位置,然后做入队操作,执行完后 rear 移到新的队尾位置。链式存储中,需要将新的结点添加到链表尾部,首先把 a4 赋值给 rear.next,然后新结点 a4 成为新的尾部结点。

微信图片12.png

2. 出队


顺序存储中进行出队操作,通过 front 定位并获取队头元素,然后做出队操作,执行完后 front 移动到新的队头位置。链式存储中,做出队操作时,获取到头部结点元素 a1 后,然后直接把 front.next 赋值给 front 来实现队头元素的删除。

微信图片11.png下面新建一个队列常规操作的接口,然后我们分别使用顺序结构(数组)和链式结构来实现它,读者可以分别对两种存储结构实现的接口的时间复杂度进行分析。

public interface Queue<T> {
    /**
     * 入队
     */
    boolean add(T t);
    /**
     * 出队
     */
    T remove();
    /**
     * 判断队列是否为空
     */
    boolean isEmpty();
    /**
     * 打印队列所有数据
     */
    void print();
}


三、队列的基本操作实现



和线性表实现一样,顺序结构使用数组来存储数据,链式结构使用结点来存储数据。


1. 顺序存储实现

public class ArrayQueue<T> implements Queue<T> {
    private int front = 0;
    private int rear = 0;
    private int size = 0;
    private Object[] elementData;
    public ArrayQueue(int size) {
        this.elementData = new Object[size];
    }
    @Override
    public boolean add(T t) {
        if (front == rear && size == elementData.length) {
            throw new ArrayIndexOutOfBoundsException();
        }
        elementData[rear] = t;
        rear = (rear + 1) % elementData.length;
        size++;
        return true;
    }
    @SuppressWarnings("unchecked")
    @Override
    public T remove() {
        if (front == rear && size == 0) {
            throw new NullPointerException();
        }
        Object t = elementData[front];
        elementData[front] = null;
        front = (front + 1) % elementData.length;
        size--;
        return (T) t;
    }
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
    @Override
    public void print() {
        System.out.println(Arrays.toString(elementData));
    }
}


2. 链式存储实现

public class LinkedQueue<T> implements Queue<T> {
    private Node front;
    private Node rear;
    private int size = 0;
    private class Node {
        private T t;
        private Node next;
        public Node() {
        }
        public Node(T t, Node next) {
            this.t = t;
            this.next = next;
        }
    }
    @Override
    public boolean add(T t) {
        Node n = new Node(t, null);
        if (rear != null) {
            rear.next = n;
        }
        if (front == null) {
            front = n;
        }
        rear = n;
        size++;
        return false;
    }
    @Override
    public T remove() {
        if (front == null) {
            throw new NullPointerException();
        }
        T t = front.t;
        front = front.next;
        size--;
        return t;
    }
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
    @Override
    public void print() {
        Node n = front;
        while (n != null) {
            System.out.print(n.t + ",");
            n = n.next;
        }
        System.out.println();
    }
}


目录
相关文章
|
存储 文件存储 数据安全/隐私保护
文件管理介绍
文件管理是操作系统中的一个重要组成部分,它负责管理计算机系统中的文件和文件系统的组织结构。文件是存储在存储介质上的一组相关数据,可以是文本文件、图像文件、音频文件、视频文件等。文件管理的目标是有效地组织、存储、检索和保护文件,提供方便的文件操作和共享功能。 文件管理的主要功能包括文件存储和文件操作两个方面: 1. 文件存储: - 文件组织结构:文件系统采用一种层次化的组织结构,常见的有层次目录结构、索引结构和扁平文件结构等。层次目录结构是最常见的文件组织方式,通过目录和子目录的层次关系来组织文件。索引结构是利用索引表来存储文件的位置和属性信息,可以提高文件的访问速度。扁平文件结构是将
695 1
|
5月前
|
SQL 存储 供应链
如何开发ERP系统中的库存管理板块(附架构图+流程图+代码参考)
本文介绍如何通过ERP系统实现企业库存管理的数字化与自动化,涵盖仓库管理、库位管理、出入库操作、库存调拨与盘点等功能设计,并提供开发技巧及代码参考,帮助企业提升库存管理效率,减少错误与资源浪费。
|
4月前
|
C++
什么是单项式
单项式是代数式中的一种
|
4月前
|
Java 测试技术 API
2025 年 Java 开发者必知的最新技术实操指南全览
本指南涵盖Java 21+核心实操,详解虚拟线程、Spring Boot 3.3+GraalVM、Jakarta EE 10+MicroProfile 6微服务开发,并提供现代Java开发最佳实践,助力开发者高效构建高性能应用。
750 4
|
运维 Cloud Native 持续交付
云原生架构的未来演进:打造灵活、高效的企业IT基础
随着数字化转型的不断深入,企业的IT基础设施正经历着从传统架构向云原生架构的根本转变。本文将探讨云原生技术的最新发展趋势,分析其在提高业务敏捷性、降低运维成本以及促进技术创新方面的关键作用。我们将重点讨论如何借助容器化、微服务、DevOps和持续交付等核心技术,构建一个能够适应快速变化市场需求的云原生生态系统。通过实际案例分析,揭示企业在迁移到云原生架构过程中面临的挑战与解决策略,为读者呈现一幅云原生技术赋能企业未来的蓝图。
|
10月前
|
机器学习/深度学习 人工智能 弹性计算
阿里云《AI 剧本生成与动画创作》解决方案深度评测
阿里云《AI 剧本生成与动画创作》解决方案深度评测
463 7
|
7月前
|
存储 安全 Android开发
HarmonyOS实战:一招搞定保存图片到相册
本文介绍了在鸿蒙系统中实现保存图片到相册的功能,包括申请权限和使用系统安全控件两种方式。文中详细讲解了如何通过网络请求下载图片并保存为本地文件,以及如何将指定布局生成图片并保存。鸿蒙系统对权限管理较为严格,推荐使用系统提供的安全控件(如 SaveButton)以保护用户隐私,避免手动申请权限。此外,文章还对比了鸿蒙与 Android/iOS 的实现差异,指出鸿蒙在功能实现上更简单,但需注意权限规范以确保项目顺利上线。
1019 0
HarmonyOS实战:一招搞定保存图片到相册
|
机器学习/深度学习 人工智能 自然语言处理
人工智能浪潮下的自然语言处理技术演进
本文从自然语言处理(NLP)技术的历史发展出发,深入剖析了在人工智能(AI)大潮中该领域的创新突破。我们将探讨深度学习如何推动语言模型的革新、多语言处理技术的发展,以及机器翻译和语音识别的最新进展。文章还将讨论这些技术进步如何影响社会,并展望未来NLP技术的潜力与挑战。
474 0
|
设计模式 Java 程序员
《On Java 8》中文版,又名《Java 编程思想》中文第五版
《On Java 8》中文版,又名《Java 编程思想》中文第五版
613 0
|
芯片
STM32速成笔记(五)—串口通信
本文介绍了串口通信的概念,用途以及一些相关概念。介绍了如何进行printf重定向,如何根据接收到的特定信息,执行特定操作。此外,本文以通过上位机发送特殊指令控制LED亮灭的小项目,给出了详细的配置方法和程序设计。
765 0
STM32速成笔记(五)—串口通信