相比于栈只能在一端进行操作而言,队列则是可以在两端进行操作的数据结构,类似于日常生活中,排队的情形一样,从队尾插入元素,队头删除元素,简称”尾插头删"。
采用头指针指向队头,尾指针指向队尾,入队时,采用尾插法,出队时,改变头节点指向下一节点。
下面就是使用单链表的物理存储结构来实现队列这种逻辑结构,具体代码如下:
- 实现的功能有基本的入队、出队、判空、求长度、迭代器遍历。
- 实现代码:
public class Queue<T> implements Iterable<T> {
// 成员变量,头尾指针
private Node<T> head;
private Node<T> last;
private int N;
// 内部节点类
private class Node<T> {
private T elem;
private Node<T> next;
public Node(T elem, Node<T> next) {
this.elem = elem;
this.next = next;
}
}
public Queue() {
this.head = new Node<>(null, null);
this.last = null;
this.N = 0;
}
public boolean isEmpty() {
return this.N == 0;
}
public int getLen() {
return this.N;
}
// 入队,采用尾插法
public void enQueue(T elem) {
Node<T> newNode = new Node<>(elem, null);
// 如果链表为空
if (head.next == null) {
this.last = newNode;
this.head.next = last;
} else {
last.next = newNode;
last = newNode;
}
this.N++;
}
// 出队,从头去除元素
public T deQueue() {
// 判断链表是否为空
if (isEmpty()) {
System.out.println("链表为空,无法删除元素");
return null;
}
// 记录要删除元素,并改变头指针指向
T elem = this.head.next.elem;
this.head.next = this.head.next.next;
this.N--;
// 再次判空,如果删除一个元素之后为空,那么就让last重新指向null
if (isEmpty()) {
this.last = null;
}
return elem;
}
// 实现迭代器方法
@Override
public Iterator<T> iterator() {
return new MyIter();
}
private class MyIter implements Iterator<T> {
private Node<T> node = head;
@Override
public boolean hasNext() {
return node.next != null;
}
@Override
public T next() {
node = node.next;
return node.elem;
}
}
}