数据结构(3):队列的原理和实现

完整代码拉到最底下

一、介绍

队列顾名思义就像我们生活中排队一样,先进先出。

如上图所示,25、16、5、9依次在队列中,按照顺序拿出的数据也分别是25、26、5、9。

二、实现过程及思路

底层使用数组来实现,实现的功能有插入数据到队尾、移除队首数据、查看队首数据、判断队列是否为空、判断队列是否存满。

将队列的元素存储在数组的某个区间内,队列在数组中是连续的,所以使用变量标记队列在数组中的位置。

1、编写类及属性

我们可以使用elements变量标记队列中元素的数量,使用front变量标记队首元素在数组的索引,end变量标记队尾元素在数组中的索引。

public class MyQueue {

    private Object[] arr;//存放队列元素的数组
    private int elements;//队列元素数量
    private int front;//队头元素在数组中的索引
    private int end;//队尾元素在数组中的索引

    public MyQueue() {
        arr = new Object[10];
        elements = 0;
        front = 0;
        end = -1;
    }

    public MyQueue(int maxSize) {
        arr = new Object[maxSize];
        elements = 0;
        front = 0;
        end = -1;
    }
}

2、队列是否为空

标记队列元数量的变量 elements 为 0 即为空

public boolean isEmpty() {
    return elements == 0;
}

3、队列是否已经满了

队列元素个数与数组的长度相等即为满

public boolean isFull() {
    return elements == arr.length;
}

4、获取队头元素

获取数组中索引为 front的元素

public Object peek() {
    return arr[front];
}

5、移除队首元素

每次都是移除数组中索引为 front 的元素,下一个元素就变成了队首,即front+1,队列元素个数elements-1。共有三种情况要考虑,如果队列已经空了就无须做任何操作,如果已经是最后一个元素,直接将标记位置的变量重置即可,其他情况正常操作。

public Object remove() {
    if (isEmpty()) {
        throw new RuntimeException("队列已经是空的,放心使用吧");
    }
    Object value = arr[front++];
    //如果已经是最后一个元素了,将指针重置即可
    if (elements == 1) {
        end = -1;
        front = 0;
        elements = 0;
    } else {
        elements--;
    }
    return value;
}

6、插入

我们编写一个持续可用的队列,所以要考虑到以下情况。

(1)存储队列的数组满了(队列满了),这个好理解,满了就无法向队尾加入元素了。

(2)因为队列在数组中是连续的,如果队列的元素在数组中最后,需要将元素从队首到队尾移到数组中第一位,也就是将后面的位置空出来(参考下图)。

public void insert(Object value) {
    //检测队列是否已经满了
    if (isFull()) {
        throw new RuntimeException("队列内元素已达到设定长度");
    }

    //如果后面没有空位置,将余下元素放到数组的头
    if (elements > 1 && end == arr.length - 1) {
        int i = 0;
        for (; i < elements; i++, front++) {
            arr[i] = arr[front];
        }
        front = 0;
        end = i-1;
    }
    //其他情况正常向后添加元素
    arr[++end] = value;
    elements++;
}

7、测试

public static void main(String[] args) {
    MyQueue queue = new MyQueue(4);
    queue.insert(11);
    queue.insert(12);
    queue.insert(13);
    queue.insert(14);

    queue.remove();
    queue.remove();
    queue.insert(16);
    //queue.remove();
    //queue.remove();

    //queue.insert(19);
    //queue.insert(20);
    queue.remove();

    queue.remove();

    queue.insert(21);
    queue.insert(22);

    while (!queue.isEmpty()) {
        System.out.println(queue.remove());
    }
}

三、完整代码

package com.jikedaquan.datastruct;

public class MyQueue {
    private Object[] arr;
    private int elements;//队列元素数量
    private int front;//队头元素在数组中的索引
    private int end;//队尾元素在数组中的索引

    public MyQueue() {
        arr = new Object[10];
        elements = 0;
        front = 0;
        end = -1;
    }

    public MyQueue(int maxSize) {
        arr = new Object[maxSize];
        elements = 0;
        front = 0;
        end = -1;
    }

    //从队尾插入
    public void insert(Object value) {
        //检测队列是否已经满了
        if (isFull()) {
            throw new RuntimeException("队列内元素已达到设定长度");
        }

        //如果后面没有空位置,将余下元素放到数组的头
        if (elements > 1 && end == arr.length - 1) {
            int i = 0;
            for (; i < elements; i++, front++) {
                arr[i] = arr[front];
            }
            front = 0;
            end = i-1;
        }
        arr[++end] = value;
        elements++;

    }

    //删除数据,从队头删除
    public Object remove() {
        if (isEmpty()) {
            throw new RuntimeException("队列已经是空的,放心使用吧");
        }
        Object value = arr[front++];
        //如果已经是最后一个元素了,将指针重置即可
        if (elements == 1) {
            end = -1;
            front = 0;
            elements = 0;
        } else {
            elements--;
        }
        return value;
    }

    //查看数据,从队头查看
    public Object peek() {
        return arr[front];
    }

    //判断是否为空
    public boolean isEmpty() {
        return elements == 0;
    }

    public boolean isFull() {
        return elements == arr.length;
    }

    public static void main(String[] args) {
        MyQueue queue = new MyQueue(4);
        queue.insert(11);
        queue.insert(12);
        queue.insert(13);
        queue.insert(14);

        queue.remove();
        queue.remove();
        queue.insert(16);
//        queue.remove();
//        queue.remove();

//        queue.insert(19);
//        queue.insert(20);
        queue.remove();

        queue.remove();

        queue.insert(21);
        queue.insert(22);

        while (!queue.isEmpty()) {
            System.out.println(queue.remove());
        }
    }
}

原文地址:https://www.cnblogs.com/AIThink/p/11620724.html

时间: 2024-11-09 02:07:41

数据结构(3):队列的原理和实现的相关文章

JUC源码分析-集合篇(五)BlockingQueue 阻塞式队列实现原理

JUC源码分析-集合篇(五)BlockingQueue 阻塞式队列实现原理 以 LinkedBlockingQueue 分析 BlockingQueue 阻塞式队列的实现原理. 1. 数据结构 LinkedBlockingQueue 和 ConcurrentLinkedQueue 一样都是由 head 节点和 last 节点组成,每个节点(Node)由节点元素(item)和指向下一个节点(next)的引用组成,节点与节点之间就是通过这个 next 关联起来,从而组成一张链表结构的队列.默认情况下

PHP实现队列的原理

关于的队列的介绍,我这里就不多讲了,随便百度一下都很多 用过laravel框架的童鞋都知道其自带队列功能,之前我很费解,PHP只是一个脚本,有超时机制,为什么能不停的去执行队列呢? 带着这个问题,在网上找了一下相关的介绍,这里我没有研究透laravel的队列,而且用这么高大上的实例来给大家讲,我估计自己都云里雾里 所以我就其原理说明一下 我们新建一个文件queue <?php while(true){ echo 1; sleep(1); } 然后中 命令行里面 执行 php queue 你会发现

简单数据结构之队列模拟

1 /************************************************************************************** 2 * Function : 模拟队列 3 * Create Date : 2014/04/23 4 * Author : NTSK13 5 * Email : [email protected] 6 * Copyright : 欢迎大家和我一起交流学习,转载请保持源文件的完整性. 7 * 任何单位和个人不经本人允许不

数据结构 - 链队列的实行(C语言)

数据结构-链队列的实现 1 链队列的定义 队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已, 我们把它简称为链队列.为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点,如下图所示. 空队列时,front和rear都指向头结点,如下图所示. 链队列的结构为: typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */ typedef struct QNode /* 结点结构 */ { QElemTy

数据结构 - 顺序队列的实行(C语言)

数据结构-顺序队列的实现 1 顺序队列的定义 线性表有顺序存储和链式存储,队列作为一种特殊的线性表,也同样存在这两种存储方式.我们先来看队列的顺序存储结构. 队列的顺序储存结构:用数组存储队列,为了避免当只有一个元素时,队头和队尾重合使得处理变得麻烦,所以引入两个指针:front指针指向队头元素,rear指针指向队尾元素的下一个位置,当front=rear时,为空队列,结构如下图所示. 假设是长度为5的数组,初始状态,空队列如下图左所示,front与 rear指针均指向下标为0的位置.然后入队a

数据结构之队列and栈总结分析

一.前言: 数据结构中队列和栈也是常见的两个数据结构,队列和栈在实际使用场景上也是相辅相成的,下面简单总结一下,如有不对之处,多多指点交流,谢谢. 二.队列简介 队列顾名思义就是排队的意思,根据我们的实际生活不难理解,排队就是有先后顺序,先到先得,其实在程序数据结构中的队列其效果也是一样,及先进先出.    队列大概有如下一些特性: 1.操作灵活,在初始化时不需要指定其长度,其长度自动增加(默认长度为32) 注:在实际使用中,如果事先能够预估其长度,那么在初始化时指定长度,可以提高效率    

数据结构专题——队列的应用 A1056.Mice and Rice ( 25)

#include <bits/stdc++.h> #include<math.h> #include <string> using namespace std; const int maxn = 1010; struct mouse{ int weight;//质量 int R;//排名 }mouse[maxn]; int main(){ int np,ng,order; scanf("%d%d",&np,&ng); for(int

Netty构建分布式消息队列实现原理浅析

在本人的上一篇博客文章:Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇 中,重点向大家介绍了AvatarMQ主要构成模块以及目前存在的优缺点.最后以一个生产者.消费者传递消息的例子,具体演示了AvatarMQ所具备的基本消息路由功能.而本文的写作目的,是想从开发.设计的角度,简单的对如何使用Netty,构建分布式消息队列背后的技术细节.原理,进行一下简单的分析和说明. 首先,在一个企业级的架构应用中,究竟何时需引入消息队列呢?本人认为,最经常的情况,无非这几种:做业务解耦.事件

数据结构丨队列和栈

队列 先入先出的数据结构 在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素. 如上图所示,队列是典型的 FIFO 数据结构.插入(insert)操作也称作入队(enqueue),新元素始终被添加在队列的末尾. 删除(delete)操作也被称为出队(dequeue). 你只能移除第一个元素. 示例 - 队列 入队:您可以单击下面的 Enqueue 以查看如何将新元素 6 添加到队列中. ? Enqueue 出队:您可以单击下面的 Dequeue 以查看将删除哪个元素. Dequeue