数据结构之Java Queue

2018-11-20  本文已影响37人  郑印

本文从通过Java Array 实现一个简单的队列和循环队列,最后对Java Queue 接口及其子类的特点进行一个总结

队列的存储结构

队列与栈不同,是一种先进先出的数据结构,元素从对头读取从队尾写入
示意图如下:

timg.jpeg

本文将使用Java 数组 来实现一个简单队列和一个循环队列,首先定义一个接口

public interface MyQueue<E> {
  boolean enqueue(E e);
  E dequeue();
}

简单队列

代码逻辑参考注释


public class MyArrayQueue<E>  implements MyQueue<E>{

    private Object[] elements;
    private int capacity;
    private int head = 0;
    private int tail = 0;

    public MyArrayQueue(int capacity){
        this.capacity = capacity;
        elements = new Object[this.capacity];
    }

    /**
     * 入队 O(n)
     * 1. tail == capacity , 并且 head == 0 代表队列没有可用空间
     * 2. 当队列有可用空间时,进行数据搬移
     * @param e
     * @return
     */
    public boolean enqueue(E e) {
        if(tail == capacity){
            // 队列满了
            if(head == 0){
                return false;
            }
            for(int i=head;i<tail;i++){
                elements[i-head] = elements[i];
            }
            tail = tail - head;
            head = 0;
        }
        this.elements[tail] = e;
        tail ++;
        return true;
    }

    /**
     * 出队 O(1)
     * @return
     */
    @SuppressWarnings("unchecked")
    public E dequeue() {
        if(head == tail){
            return null;
        }
        E e = (E)elements[head];
        head ++;
        return e;
    }
}

测试

  @Test
    public void myArrayQueueTest(){
        MyQueue<String> queue = new MyArrayQueue<String>(5);
        queue.enqueue("a");
        Assert.assertEquals(queue.dequeue(),"a");
        queue.enqueue("b");
        Assert.assertEquals(queue.dequeue(),"b");
        queue.enqueue("c");
        Assert.assertEquals(queue.dequeue(),"c");
        queue.enqueue("d");
        queue.enqueue("e");
        queue.enqueue("f");
        queue.enqueue("g");
        queue.enqueue("h");
        Assert.assertFalse(queue.enqueue("s"));
        Assert.assertEquals(queue.dequeue(),"d");
        Assert.assertEquals(queue.dequeue(),"e");
        Assert.assertEquals(queue.dequeue(),"f");
        Assert.assertEquals(queue.dequeue(),"g");
        Assert.assertEquals(queue.dequeue(),"h");
        Assert.assertNull(queue.dequeue());
    }

上个队列中,当队列慢时有数据搬移工作,整体效率不够,所有有了循环队列的实现

循环队列


public class MyCircularQueue<E> implements MyQueue<E> {

   private Object[] elements;
   private int capacity;
   private int head = 0;
   private int tail = 0;

   public MyCircularQueue(int capacity){
       this.capacity = capacity;
       elements = new Object[capacity];
   }

   /**
    * 入队 O(1)
    * 1. (tail+1) % capacity == head 队满,比如 capacity = 5 , tail = 4 , head = 0
    * 2. tail 元素添加后 tail 往后移动一位,当等于capacity 重新归 0
    * @param e
    * @return
    */
   public boolean enqueue(E e) {
       if((tail+1) % capacity == head){
           return false;
       }
       this.elements[tail] = e;
       tail = (tail+1) % capacity;
       return true;
   }

   /**
    * 出队 O(1)
    * 1. head == tail 空队列
    * 2. 去除元素后 head 往后移动一位,当等于capacity 重新归 0
    * @return E
    */
   @SuppressWarnings("unchecked")
   public E dequeue() {
       if(head == tail){
           return null;
       }
       E e = (E)elements[head];
       head = (head+1) % capacity;
       return e;
   }
}

测试

@Test
    public void myCircularQueueTest(){
        MyQueue<String> queue = new MyCircularQueue<String>(5);
        queue.enqueue("a");
        Assert.assertEquals(queue.dequeue(),"a");
        queue.enqueue("b");
        Assert.assertEquals(queue.dequeue(),"b");
        queue.enqueue("c");
        Assert.assertEquals(queue.dequeue(),"c");
        queue.enqueue("d");
        queue.enqueue("e");
        queue.enqueue("f");
        queue.enqueue("g");
        Assert.assertFalse(queue.enqueue("h"));
        Assert.assertEquals(queue.dequeue(),"d");
        Assert.assertEquals(queue.dequeue(),"e");
        Assert.assertEquals(queue.dequeue(),"f");
        Assert.assertEquals(queue.dequeue(),"g");
        Assert.assertNull(queue.dequeue(),"h");
    }

队列作为一种重要的数据格式,在实际应用开发中占有重要地位,本文实现的队列都比较简单,在Java中根据队列不同的应用场景做了不一样的封装,下面总结一下Java 语言中不同队列的特点

Java Queue 接口

Queue接口在java.util包中可用,并扩展了Collection接口。队列集合用于保存要处理的元素,并提供各种操作。它是一个有序的对象列表,其使用仅限于在列表末尾插入元素并从头开始删除元素列表,即它遵循FIFO或先入先出原则。Queue的特征:

操作方法上的一些差别

本文是学习极客时间数据结构与算法之美结合Java语言的一些笔记,如果你对此课程感兴趣可以在下载极客时间App搜索该课程,也可以点击下面链接查看
数据结构与算法之美

上一篇 下一篇

猜你喜欢

热点阅读