1.队列
队列是一种非常常见的数据结构,基本思想是先进先出,即FIFO(Fist In First Out),队列的第一个元素称为队首,最后一个元素称为队尾。
2.实现方法
队列可以通过链表和数组来进行实现,使用数组进行实现,一般会面临假溢出的问题,因此,在使用数组实现时,一般都会定义成循环队列。但是,我们可以使用链表来规避这个问题。
3.实现过程
首先定义队列类 class Queue{}
public class Queue<T> implements Iterable<T>{}
我们可以让这个类实现Iterable接口,便于我们来遍历队列。
我们使用链表来实现队列。接着要定义我们的链表结点类class Node{},定义在队列类里面,可以设置为私有的
private class Node {}
节点类中有两个成员变量和一个构造方法
private class Node {
private T item;
private Node next;
public Node(T t, Node next) {
this.item = t;
this.next = next;
}
}
item用来存放结点的值,next用来存放下一个结点的值。
队列类中有三个成员变量和一个构造方法
public class Queue<T> implements Iterable<T>{
private Node head;
private int N;
private Node last;
public Queue() {
this.head = new Node(null, null);
this.N = 0;
// last 要初始化为null,不能初始化为一个null结点,否则会导致无法出队
this.last = null;
}
}
N表示的是当前队列中有几个元素,head表示队头元素,last表示队尾元素。
在队列类中设计了4个方法
// 获取队列长度
public int length() {
return N;
}
// 判断队列是否为空
public boolean isEmpty() {
return N == 0;
}
// 入队一个元素
public void insert_Queue(T t) {
// 判断队列是否为空
if (last == null) {
last = new Node(t, null);
head.next = last;
} else {
Node temp = last;
last = new Node(t, null);
temp.next = last;
}
// 元素个数加一
N++;
}
// 出队一个元素
public T out_Queue() {
Node temp = head.next;
// 判断是否为空
if (isEmpty()) {
throw new NullPointerException("队列空,没有元素");
}
T t = temp.item;
head.next = temp.next;
// 元素个数减一
N--;
// 如果所有的的元素都出队列了,应当重置last为空,否则会出现问题
if (isEmpty()) {
last = null;
}
return t;
}
队列的假溢出问题,会体现在出队上,因此在出队这个方法中我们加上一个判断,如果所有的元素都出队了,就重置队尾元素last为null,这样就可以完美的解决假溢出的问题了。至此,关于使用链表模拟队列的基本代码我们就全部写完了(Iterable接口的实现请移步至全部代码中)。
4.全部代码
import java.util.Iterator;
/*
* @author: XiaoQi Si
* @date: 2021/7/22 18:19
* @Email: 2054927620@qq.com
* @SoftWare: IDEA
*/
public class Queue<T> implements Iterable<T>{
/**
* 使用链表模拟队列
*/
private Node head;
private int N;
private Node last;
private class Node {
private T item;
private Node next;
public Node(T t, Node next) {
this.item = t;
this.next = next;
}
}
// 构造方法
public Queue() {
this.head = new Node(null, null);
this.N = 0;
// last 要初始化为null,不能初始化为一个null结点,否则会导致无法出队
this.last = null;
}
// 获取队列长度
public int length() {
return N;
}
// 判断队列是否为空
public boolean isEmpty() {
return N == 0;
}
// 入队一个元素
public void insert_Queue(T t) {
// 判断队列是否为空
if (last == null) {
last = new Node(t, null);
head.next = last;
} else {
Node temp = last;
last = new Node(t, null);
temp.next = last;
}
// 元素个数加一
N++;
}
// 出队一个元素
public T out_Queue() {
Node temp = head.next;
// 判断是否为空
if (isEmpty()) {
throw new NullPointerException("队列空,没有元素");
}
T t = temp.item;
head.next = temp.next;
// 元素个数减一
N--;
// 如果所有的的元素都出队列了,应当重置last为空,否则会出现问题
if (isEmpty()) {
last = null;
}
return t;
}
// 实现Iterable接口便于遍历
@Override
public Iterator<T> iterator() {
return new SIterator();
}
private class SIterator implements Iterator{
private Node N;
public SIterator(){
this.N = head;
}
@Override
public boolean hasNext() {
return N.next != null;
}
@Override
public Object next() {
N = N.next;
return N.item;
}
}
}
5.结语
队列是一种十分常见的数据结构,使用链表来实现它,我们只需要在出队方法中加上一个判断,就可以规避假溢出的问题。