【数据结构与算法】Java —— 理论 七:队列

版权声明:本文为博主原创文章,未经博主允许不得转载。



一、队列:Queue

1.1 介绍

  • 队列 是一种特殊的线性表,只能在 头尾两端 操作
  • 队尾(rear): 只能从 队尾添加元素, 一般叫做 enQueue, 入队
  • 对头(front): 只能从队头移除 元素, 一般叫做 deQueue, 出队
  • 先进先出的原则,First In First Out,FIFO
  • 队列的内部实现可以使用 动态数组双向链表 实现
  • 优先使用双向链表,因为队列主要是往头尾操作 元素

在这里插入图片描述

1.2 接口设计

public class Queue<E> {
   
    // 使用双向链表实现队列
    private List<E> list = new LinkedList<>();
    // 元素的数量
    public int size();
    // 是否为空
    public boolean isEmpty();
    // 入队
    public void enQueue(E element);
    // 出队
    public E deQueue();
    // 获取队列的头元素
    public E front();
}

1.3 方法实现

public class Queue<E> {
   
    private List<E> list = new LinkedList<>();
	
    public int size() {
   
        return list.size();
    }

    public boolean isEmpty() {
   
        return list.isEmpty();
    }

    public void enQueue(E element) {
   
        list.add(element);
    }

    public E deQueue() {
   
        return list.remove(0);
    }

    public E front() {
   
        return list.get(0);
    }
}

1.4 队列分类

1.4.1 双端队列

1.4.1.1 双端队列:Deque
  • 双端队列是能在 头尾 两端 添加、删除 的队列

在这里插入图片描述

1.4.1.2 双端队列的接口设计&实现
public class Deque<E> {
   
    private List<E> list = new LinkedList<>();
	
    // 元素的数量
    public int size() {
   
        return list.size();
    }
    // 是否为空
    public boolean isEmpty() {
   
        return list.isEmpty();
    }
    // 从队头出队
    public E deQueueFront() {
   
        return list.remove(0);
    }
    // 从队头入队
    public void enQueueFront(E element) {
   
        list.add(0, element);
    }
    // 从队尾入队
    public void enQueueRear(E element) {
   
        list.add(element);
    }
    // 从队尾出队
    public E deQueueRear() {
   
        return list.remove(list.size() - 1);
    }
    // 获取队列的头元素
    public E front() {
   
        return list.get(0);
    }
    // 获取队列的尾元素
    public E rear() {
   
        return list.get(list.size() - 1);
    }
}

1.4.2 循环队列

1.4.2.1 循环队列:Circle Queue

在这里插入图片描述

  • 使用一个索引变量 front 控制第 0 个元素所在位置
  • 每一次 出栈,就将 front 位置的元素取出并删除,然后 front 向后 +1
    在这里插入图片描述
  • 每一次 入栈,都根据 front 和当前元素数量计算出入栈元素应该存入的索引,然后将元素存入到数组对应索引的位置上在这里插入图片描述
1.4.2.2 循环队列的接口设计
public class CircleQueue<E> {
   
    // 记录第0个元素的索引
    private int front;
    // 当前队列存储的元素个数
    private int size;
    // 用来存储元素的数组
    private E[] elements;
    // 当前队列存储的元素数量
    public int size();
    // 当前队列是否为空
    public boolean isEmpty();
    // 入队
    public void enQueue(E element);
    // 出队
    public E deQueue();
    // 查看索引为0的元素
    public E front();
}
1.4.2.3 循环队列的实现
1.4.2.3.1 构造方法
  • 如果构建的数组空间小于默认空间,则会以默认空间构建数组
public class ArrayList<E> {
   
    private E[] elements;
    // 设置elements数组默认的初始化空间
    private static final int DEFAULT_CAPACITY = 10;
	
    public CircleQueue() {
   
        elements = (E[]) new Object[DEFAULT_CAPACITY];
    }
}
1.4.2.3.2 入队
  • 入队前需要考虑两个问题:队列是否需要扩容计算入队实际索引
1.4.2.3.2.1 数组扩容
private void ensureCapacity(int capacity) {
   
    int oldCapacity = elements.length;
    if (oldCapacity >= capacity) return;
		
    // 新容量为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1); //位运算
    E[] newElements = (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
   
        newElements[i] = elements[index(i)];
    }
    elements = newElements;
		
    // 重置front
    front = 0;
}
1.4.2.3.2.1 索引计算
  • 预期入队索引 = 第0个元素索引 + 当前队列元素个数
  • 如果 预期入队索引 大于等于 数组长度实际入队索引 = 预期入队索引 数组长度
  • 如果 预期入队索引 小于 数组长度实际入队索引 = 预期入队索引
private int index(int index) {
   
    index += front;
    return index - (index >= elements.length ? elements.length : 0);
}

那么入队的代码如下

public 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

InitialHeart2021

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值