链表之初级队列实现

11 阅读3分钟

队列

一说到队列,大家应该很容易想到跟排队有关的事,毕竟咱们泱泱中华一大特色人多哈哈!

计算机中的队列同现实世界的队列几乎相同,举个栗子🌰:午饭前的最后一节课的下课铃一响,人们乌央乌央的都走向食堂(干饭人都是用跑的😄)。

打饭的时候来的最早的人排在最前面,之后依次排开,先到的先打饭,后到的喝稀饭...非常明显的先进先出(FIFO)形式。

在我的博文中目前实现的都是比较简单基础的数据结构,不管是栈、队列还是背包(集合),都比较基础,我觉得首先要把这些基础的写的非常熟练,只要一下手立马能写出来的程度,才能真正搞懂之后复杂一些的数据结构,这一点尤为重要。 说到这里就得说代码量积累了,需要相当程度的有效代码量,才能真正踏入编程的门槛。

骐骥一跃不能十步,驽马十驾功在不舍

设计思路

同上一篇用链表设计下压栈一样,我们还是使用链表,API方法的设计几乎与下压栈相同。 我们需要队列来存取数据,那么就离不开这两个方法:入列enqueue()、出列dequeue().
其它如size()方法Iterator等基本与下压栈相同。

上代码实现


import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 单链表实现的队列
 * @author wangxinfu
 */
public class Queue<Item> implements Iterable<Item>{
    /**
     * 实际元素数量
     */
    private int size;
    /**
     * 最早添加的结点
     */
    private Node first;
    /**
     * 最近添加的结点,尾节点
     */
    private Node last;

    /**
     * 私有内部类作为栈结构
     */
    private class Node{
        Item item;
        Node next;
    }

    /**
     * 添加遍历iterator的方法
     */
    private class QueueIterator implements Iterator<Item>{
        /**
         * 指向当前结点
         */
        private Node current = first;
        /**
         * 是否为空
         * @return
         */
        @Override
        public boolean hasNext() {
            return current!=null;
        }

        /**
         * 从队列的头部,每次调用返回查看一个元素
         * @return
         */
        @Override
        public Item next() {
            if(!hasNext()){
                throw new NoSuchElementException("Queue is empty!");
            }
            Item item = current.item;
            current = current.next;
            return item;
        }
    }

    /**
     * 元素添加到队列(从尾部添加)
     * @param item
     */
    public void enqueue(Item item){
        //从尾部添加 last之后
        Node oldLast = last;
        last = new Node();
        last.item = item;
        //判断是否是为空队列,空队列则这次为第一个结点,既是
        //首结点也是尾节点,否则就是last之后的添加结点
        if (isEmpty()){first = last;}
        else{oldLast.next = last;}
        size++;
    }

    /**
     * 出列
     * @return item
     */
    public Item dequeue(){
        if (isEmpty()){
            throw new NoSuchElementException("Queue is empty!");
        }
        //暂存first
        Item item = first.item;
        Node next = first.next;
        //help GC回收垃圾
        first.item = null;
        first.next = null;
        first = next;
        size--;
        return item;
    }

    public int size(){return size;}

    public boolean isEmpty(){return first == null;}

    @NotNull
    @Override
    public Iterator<Item> iterator() {
        return new QueueIterator();
    }
    //test
    public static void main(String[]args){
        Queue<String> queue = new Queue<>();
        for (int i=0; i<1000; i++){
            queue.enqueue(""+i);
        }
        System.out.println("Queue size: "+ queue.size());
        Iterator<String> iterator = queue.iterator();
        System.out.println("=====================================");
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        System.out.println("=====================================");
        for (int i = 0;i< 100;i++){
            System.out.println(queue.dequeue());
        }
        System.out.println(queue.size());
    }
}

一定要亲手操作,多写几遍,否则,到了以简单数据结构为基础的更复杂结构,直接歇菜了。 下一篇将封装一个集合(背包),该系列基本按照经典数据《算法》第4版的内容排列写下去,部分代码与内容也源自此处。