1.队列的概念:
只允许在一端进行插入数据操作,在另一端进行删除数据操作的线性表,队列具有先进先出FIFO 入队列 :进行插入操作的一端称为队尾.
出队列:进行删除操作的一端称为队头。
图例如下:
2.Queue是一个接口,底层是通过链表实现的
2.队列对应的一些方法:
3.模拟队列的实现:
底层以双向链表为例:
其结构和双向链表类似,包括:前驱指针,后驱指针,数据域
构造方法:数据域的传入。
队头、队尾、以及有效元素个数的定义。
具体代码如下:
public class MyQueue {
//双向链表创建队列
public static class ListNode{
public ListNode next; //前驱节点
public ListNode prev; //后驱节点
public int val;
ListNode(int val)
{
this.val = val;
}
}
public ListNode first = null; // (队头)头节点
public ListNode last = null; //(队尾)尾节点
public int usedSize = 0; //有效元素
3.1:offer(入队列)功能的实现:
创建一个新节点node来接受val的值
在尾插之前,判断链表是否为空(第一次插入,有效元素为0)如果是第一次插入,则队头队尾均为node。
若不是第一次插入,进行尾插操作:
具体代码如下:
public void offer(int val){
ListNode node = new ListNode(val);
if(isEmpty()){
first = last = node;
}else{
last.next = node;
node.prev = last;
last = last.next;
}
usedSize++;
}
public boolean isEmpty(){
return usedSize == 0; (有效元素为零,返回false,继续执行 否则为true,退出)
}
}
3.2 出队列功能的实现:
-
出栈操作:当调用出栈方法时,你首先需要检查队列是否为空(即
first
是否为null
)。如果队列不为空,你将执行出栈操作。 -
移动头节点:在将
first
指向下一个节点后,新的first
可能为null
,这表示队列已经为空。 -
更新前驱指针:
- 如果
first
不为空:这意味着队列仍然有元素。在这种情况下,新的first
的prev
应该被设置为null
,以表示它是新的队头节点。 - 如果
first
为空:这意味着所有节点都已经被移除,因此就不需要更新first.prev
。此时,last
也应被设置为null
,表示队列已经完全空了。
- 如果
- 具体代码如下:
public int poll() { if (first == null) { // 检查队列是否为空 return null; // 如果为空,返回 null } int value = first.val; // 获取队头元素 first = first.next; // 移动头节点 if (first != null) { // 如果队列不为空,更新头节点的前驱 first.prev = null; // 将新队头节点的前驱设置为 null } else { // 如果队列为空,更新尾节点 last = null; // 更新尾节点为 null } usedSize--; return value; // 返回出队的值 }
3.2:peek(获取队头元素的实现:)
判断队列是否为空,如果为空,返回-1,否则返回first队头的值
具体代码如下:
public int peek(){
//获取栈顶元素
if(isEmpty()){
return -1; //链表为空
}
return first.val;
}
public boolean isEmpty(){
return usedSize == 0;
}
今天的分享就到这里,喜欢的老铁来个三联吧!