首页 > 其他分享 >4、循环队列

4、循环队列

时间:2023-04-10 14:34:16浏览次数:27  
标签:队列 tail length 循环 front data public size

1、循环队列

我们上次基于动态数组实现的队列,出队是 O(n) 级别的,非常的 low,这里我用另外一种思路来实现队列
我们使用两个变量 front 和 tail,分别代表数组第一个元素的索引和最后一个元素的后一个索引
使用 data[front] 出队,data[tail] 入队
队列为空:size == 0
队列为满:size == length

public class LoopQueue<E> implements Queue<E> {

    private E[] data;
    private int front;
    private int tail;
    private int size;

    public LoopQueue2(int capacity) {
        data = (E[]) new Object[capacity];
        front = tail = size = 0;
    }

    public LoopQueue2() {
        this(10);
    }

    @Override
    public void enqueue(E e) {
        if (size == data.length) resize(data.length * 2);

        data[tail] = e;
        tail = (tail + 1) % data.length;
        size++;
    }

    @Override
    public E dequeue() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        
        E ret = data[front];
        data[front] = null;
        front = (front + 1) % data.length;
        size--;
        
        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    @Override
    public E getFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return data[front];
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    public int getCapacity() {
        return data.length;
    }

    /**
     * 动态数组
     */
    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[(i + front) % data.length];
        }
        data = newData;
        front = 0;
        tail = size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("LoopQueue2: size = %d, capacity = %d\n", size, getCapacity()));
        sb.append("Front [");
        for (int i = 0; i < size; i++) {
            sb.append(data[(i + front) % data.length]);
            if (i != size - 1) sb.append(", ");
        }
        sb.append("] Tail");
        return sb.toString();
    }
}

2、双端队列

有了循环队列队列的基础,双端队列也可以非常容易的实现

public class Deque<E> {

    private E[] data;
    private int front;
    private int tail;
    private int size;

    public Deque(int capacity) {
        data = (E[]) new Object[capacity];
        front = tail = size = 0;
    }

    public Deque() {
        this(10);
    }

    public void addFront(E e) {
        if (size == data.length) resize(data.length * 2);

        front = (front != 0) ? (front - 1) : (data.length - 1);
        data[front] = e;
        size++;
    }

    public void addLast(E e) {
        if (size == data.length) resize(data.length * 2);

        data[tail] = e;
        tail = (tail + 1) % data.length;
        size++;
    }

    public E removeFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");

        E ret = data[front];
        data[front] = null;
        front = (front + 1) % data.length;
        size--;

        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    public E removeLast() {
        if (isEmpty()) throw new RuntimeException("队列为空");

        tail = (tail != 0) ? (tail - 1) : (data.length - 1);
        E ret = data[tail];
        data[tail] = null;
        size--;

        if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
        return ret;
    }

    public E getFront() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return data[front];
    }

    public E getLast() {
        if (isEmpty()) throw new RuntimeException("队列为空");
        return (tail != 0) ? data[tail - 1] : data[data.length - 1];
    }

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

    public int getSize() {
        return size;
    }

    public int getCapacity() {
        return data.length;
    }

    private void resize(int newCapacity) {
        E[] newData = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            newData[i] = data[(i + front) % data.length];
        }
        data = newData;
        front = 0;
        tail = size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("Deque: size = %d, capacity = %d\n", getSize(), getCapacity()));
        sb.append('[');
        for (int i = 0; i < getSize(); i++) {
            sb.append(data[(i + front) % data.length]);
            if (i != getSize() - 1) sb.append(", ");
        }
        sb.append(']');
        return sb.toString();
    }
}

标签:队列,tail,length,循环,front,data,public,size
From: https://www.cnblogs.com/n139949/p/17302826.html

相关文章

  • 线性表之单循环链表实现
    main.cpp#include"SCList.h"intmain(){Listmylist;InitList(mylist);intselect=1;ElemTypeItem;Node*p=NULL;while(select){printf("************************************\n");printf("......
  • 【学习笔记】rabbitmq设置队列ttl和使用延迟插件的代码示例
    文章目录设置队列ttl配置文件生产者消费者设置消息ttl延迟插件的使用修改配置文件修改生产者修改消费者设置队列ttl代码架构:创建两个队列QA和QB,两者队列TTL分别设置为10S和40S,然后在创建一个交换机X和死信交换机Y,它们的类型都是direct,创建一个死信队列QD配置文件spring.rabbitmq.h......
  • 优先级队列PriorityQueue在算法问题中的使用
    文章目录优先级队列介绍与优先级队列有关的习题[179.最大数][918.环形子数组的最大和][1094.拼车][264.丑数II]前k个出现频率最高的数字用优先级队列合并k个有序链表滑动窗口的最大值其他:对二维数组自定义排序优先级队列介绍优先队列一般基于二叉堆实现,二叉堆:堆的根节点的优......
  • 【Java 并发】【十】【JUC数据结构】【六】SynchronousQueue同步阻塞队列原理
    1 前言看过了LinkedBlockingQueue、ArrayBlockingQueue、DelayQueue等阻塞队列,这节我们又要看一个不一样的队列,SynchronousQueue同步阻塞队列。2 SynchronousQueue是什么SynchronousQueue的同步队列,使用的场景比较少,主要是用来做线程之间的数据同步传输的。线程之间的同步......
  • 【Java 并发】【十】【JUC数据结构】【五】DelayQueue延迟阻塞队列原理
    1 前言前两节我们看了BlockingQueue阻塞队列的两个子类,LinkedBlockingQueue、ArrayBlockingQueue,它们都是使用了ReentrantLock、Condition的来实现的,在进行插入操作、拉取数据操作之前为了并发安全都需要进行加锁;然后插入时候在容量满的时候发现没有空间了,这时候调用Condition.......
  • 【Java 并发】【十】【JUC数据结构】【三】LinkedBlockingQueue阻塞队列原理
    1 前言这节我们就来看看LinkedBlockingQueue内部实现的原理。2 LinkedBlockingQueue的使用在看原理之前我们先来用一用LinkedBlockingQueue,来体验一下:2.1  插入数据publicclassLinkedBlockingQueueTest{publicstaticvoidmain(String[]args)throwsInter......
  • qt事件循环
    不知道说啥直接上图,希望几个月之后我还能看得懂.原图在这儿......
  • js异步——事件循环和消息队列
    前言上篇文章中介绍了多进程的浏览器基本架构,现在,我们来谈谈单线程的JS代码、消息队列、事件循环、微任务和宏任务。单线程的JavaScript什么是单线程js?如果你已经仔细阅读过上一篇文章,那么答案是显而易见的:由于浏览器是由渲染进程的主线程来执行js代码的,换句话说,js的运......
  • 【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现
    承接上文承接上一篇文章【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)】我们基本上对层级时间轮算法的基本原理有了一定的认识,本章节就从落地的角度进行分析和介绍如何通过Java进行实现一个属于我们自己的时间轮服务......
  • 1238. 循环码排列
    题目链接:1238.循环码排列方法:格雷码解题思路令\(N=2^n-1\),将\(i=0,...,N,\)分别转换为其对应的格雷码,用\(g\)数组存储,即\(g[i]\)表示\(i\)对应的格雷码的十进制的值。由于题目中\(start\)表示的是格雷码的十进制值,且返回的为格雷码的十进制值的数组,在\(g\)......