本文最后更新于:星期四, 六月 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. 行1:
  2. 行2:
  3. 行3:

那么当调用了需多次add方法之后,就应该是这个样子:
image.png

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. 行1:

    1. 行2:


算法     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

数组实现的优先队列 上一篇
数组实现固定长度的循环队列 下一篇