一、链式队列
1. 使用双向链表实现队列,可以采用尾入,头出 也可以采用 头入、尾出 (LinkedList采用尾入、头出)
2. 下面代码实现的是尾入、头出:
package bageight;
/**
* Created with IntelliJ IDEA.
* Description:
* User: tangyuxiu
* Date: 2024-08-22
* Time: 16:44
*/
public class MyQueue<E> {
/* 使用内部类实现链表的节点 */
private class ListNode<E> {
E val;
ListNode<E> prev;
ListNode<E> next;
public ListNode(E val) {
this.val = val;
}
}
private ListNode<E> head;
private ListNode<E> last;
/* push尾入 */
public void offer(E data) {
ListNode<E> newNode = new ListNode<>(data);
//1. 如果链表为null
if (this.head == null) {
this.head = this.last = newNode;
return;
}
//2. 尾插
this.last.next = newNode;
newNode.prev = this.last;
this.last = newNode;
}
/* poll头出 */
public E poll() {
//1. 如果链表为null
if (this.head == null) {
return null;
}
//2. 头出
E del = this.head.val;
if (this.head.next == null) {//链表只有一个节点
this.head = this.last = null;
} else {//链表有多个节点
this.head = this.head.next;
this.head.prev = null;
}
return del;
}
/* peek */
public E peek() {
//1. 如果链表为null
if (this.head == null) {
return null;
}
//2. 正常
return this.head.val;
}
/* size */
public int size() {
int count = 0;
ListNode<E> cur = this.head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
}
二、循环队列
622. 设计循环队列 - 力扣(LeetCode)
【难点】:
① 到底怎么判断什么时候队列为null,什么时候队列满了
② fast++,如何不越界:fast = fast % len 或 第三种做法要写成fast = (fast + 1) % len
【等待补充】使用flag的方式如何编写代码。
2.1 使用uesdSize判断空满
class MyCircularQueue {
private int[] elem;//由于不是泛型类,且依据题意放入数组中的数据都是int类型的,
//因此如此定义
private int head;//队头位置
private int last;//待插入数据位置
private int uesdSize;//队列有效数据个数
public MyCircularQueue(int k) {
this.elem = new int[k];
}
//尾插
public boolean enQueue(int value) {
if (this.isFull()) {
return false;
}
this.elem[this.last] = value;
this.last++;
//使得last的下标一直维持在0~elem.length-1
this.last = this.last % this.elem.length;
this.uesdSize++;
return true;
}
//头删
public boolean deQueue() {
if (this.isEmpty()) {
return false;
}
//头删是让head的值++,而不是--🙀
this.head++;
this.head = this.head % this.elem.length;
this.uesdSize--;
return true;
}
//获取队头元素的值
public int Front() {
if (this.isEmpty()) {
return -1;
}
return this.elem[this.head];
}
//获取队尾元素的值
public int Rear() {
if (this.isEmpty()) {
return -1;
}
if (this.last == 0) {
return this.elem[this.elem.length - 1];
}
return this.elem[this.last - 1];
}
public boolean isEmpty() {
return this.uesdSize == 0;
}
public boolean isFull() {
return this.uesdSize == this.elem.length;
}
}
2.2 浪费一个数组空间来判断空满
class MyCircularQueue {
private int[] elem;//由于不是泛型类,且依据题意放入数组中的数据都是int类型的,
//因此如此定义
private int head;//队头位置
private int last;//待插入数据位置
public MyCircularQueue(int k) {
this.elem = new int[k + 1];
}
//尾插
public boolean enQueue(int value) {
if (this.isFull()) {
return false;
}
this.elem[this.last] = value;
this.last++;
//使得last的下标一直维持在0~elem.length-1
this.last = this.last % this.elem.length;
return true;
}
//头删
public boolean deQueue() {
if (this.isEmpty()) {
return false;
}
//头删是让head的值++,而不是--🙀
this.head++;
this.head = this.head % this.elem.length;
return true;
}
//获取队头元素的值
public int Front() {
if (this.isEmpty()) {
return -1;
}
return this.elem[this.head];
}
//获取队尾元素的值
public int Rear() {
if (this.isEmpty()) {
return -1;
}
if (this.last == 0) {
return this.elem[this.elem.length - 1];
}
return this.elem[this.last - 1];
}
public boolean isEmpty() {
return this.head == this.last;
}
public boolean isFull() {
return (this.last + 1) % this.elem.length == this.head;//🙀,想一想特殊情况就知道为什么这么写了
}
}