本文最后更新于:星期四, 六月 18日 2020, 9:01 上午
import java.util.NoSuchElementException;
public class LinkedQueue<T> {
private class Node{
private Node next;
private T element;
Node(Node next, T element) {
this.next = next;
this.element = element;
}
}
private int size;
private Node headPointer;//指向链表头结点的指针;
private Node tailPointer;//指向链表尾结点的指针;
public LinkedQueue() {
Node blankNode=new Node(null,null);//什么也不存储的头结点,用于初始化链表,并同时被头指针和尾指针引用。
headPointer=blankNode;
tailPointer=blankNode;
size=0;
}
public void add(T element) {
Node newNode=new Node(null,element);
tailPointer.next=newNode;
tailPointer=newNode;
size++;
}
public T remove() {
if (isEmpty()){
throw new NoSuchElementException("队列为空!");
}
T answer;
Node first=headPointer.next;//headPointer引用blankNode,就是是头结点,他的下一项才是真正的链表的第一个结点。
answer=first.element;
headPointer.next=first.next;
first.next=null;
size--;
return answer;
}
public boolean isEmpty() {
return size==0;//return headPointer==tailPointer;
}
public int size(){
return size;
}
public T peek(){
if (isEmpty()){
throw new NoSuchElementException("队列为空!");
}
return headPointer.next.element;
}
@Override
public String toString() {
if (isEmpty()){
return "[]";
}
StringBuilder sb=new StringBuilder("[");
Node cursor=headPointer.next;//指向第一个有意义的结点。
for (int i=0;i<size;i++){
sb.append(cursor.element.toString());
if (i!=size-1){
sb.append(",");
}
cursor=cursor.next;
}
sb.append("]");
return sb.toString();
}
}
public class Main {
public static void main(String[] args) throws Throwable {
LinkedQueue<String> q=new LinkedQueue<>();
q.add("1");
q.add("2");
q.add("3");
System.out.println(q);//[1,2,3]
q.remove();
q.remove();
System.out.println(q);//[3]
q.add("4");
q.add("5");
q.add("6");
q.add("7");
System.out.println(q);//[3,4,5,6,7]
}
分解着一个一个方法来看如何用链表实现队列:
1. 构造方法
//构造函数初始化链表
//将全局变量指向一个blankNode头结点,这个头结点什么也不做,只是用来标记这是链表的开头。
//方便操作
public LinkedQueue() {
Node blankNode=new Node(null,null);//什么也不存储的头结点,用于初始化链表,并同时被头指针和尾指针引用。
headPointer=blankNode;
tailPointer=blankNode;
size=0;
}
2. add
public void add(T element) {
Node newNode=new Node(null,element);//行1
tailPointer.next=newNode;//行2
tailPointer=newNode;//行3
size++;
}
//下面用图描述每行代码做了什么
- 行1:
- 行2:
- 行3:
那么当调用了需多次add方法之后,就应该是这个样子:
3. remove
public T remove() {
if (isEmpty()){
throw new NoSuchElementException("队列为空!");
}
T answer;
Node first=headPointer.next;//headPointer引用blankNode,就是是头结点,他的下一项才是真正的链表的第一个结点。
answer=first.element;
headPointer.next=first.next;//行1
first.next=null;//行2
size--;
return answer;
}
出队的操作,直接看图
行1:
- 行2:
- 行2: