队列概念

  队列(Queue)是限定只能在一端插入、另一端删除的线性表。允许删除的一端叫做队头(front),允许插入的一端叫做队尾(rear),没有元素的队列称为“空队列”。

  队列具有先进先出(FIFO)的特性。

普通顺序队列存在的问题

  在普通顺序队列中,入队的操作就是先将尾指针rear右移一个单位,然后将元素值赋值给rear单位。出队时,则是头指针front后移一个单位。像这样进行了一定数量的入队和出队操作后,可能会出现这样的情况:

  尾指针rear已指到数组的最后有一个元素,即rear==MaxLen-1,此时若再数组的前面部分可能还有很多闲置空间,即这种溢出并非是真的没有可用的存储空间,故称这种溢出现象为“假溢出”。显然,必须要解决这一块假溢出的问题,否则顺序队列就没有太多使用价值。

循环队列

       

说明:

  1. 判断满条件为  front =  (rear + 1) % size  即满

       2. 每入队一个元素, tail =  (tail + 1) % size

       3. 令队列空间中的一个单元闲置,使得队列非空时,rear与front之间至少间隔一个空闲单。  

 

循环队列: 

  1 public class LoopQueue<E> implements Queue<E> {
  2 
  3     private E[] data;
  4     private int front,tail;
  5     private int size;
  6 
  7     public LoopQueue(int capacity){
  8         //需要多一个空间 留空
  9         data = (E[])new Object[capacity+1];
 10         front = 0;
 11         tail = 0;
 12         size = 0;
 13     }
 14 
 15     public LoopQueue(){
 16         this(10);
 17     }
 18 
 19     public int getCapacity(){
 20         return data.length - 1;
 21     }
 22 
 23     @Override
 24     public boolean isEmpty(){
 25         return front == tail;
 26     }
 27 
 28     @Override
 29     public int getSize(){
 30         return size;
 31     }
 32 
 33     //入队
 34     @Override
 35     public void enqueue(E e){
 36         //队列满了判断
 37         if ((tail + 1) % data.length == front)
 38             resize(getCapacity() * 2);
 39 
 40         data[tail] = e;
 41         tail = (tail + 1) % data.length;
 42         size++;
 43     }
 44 
 45     //出队
 46     @Override
 47     public E dequeue(){
 48 
 49         if (isEmpty())
 50             throw new IllegalArgumentException("Cannot dequeue from an empty queue");
 51 
 52         E ret = data[front];
 53         //data[front] = null;
 54         front = (front + 1) % data.length;
 55         size --;
 56 
 57         //缩容
 58         if (size == getCapacity() / 4 && getCapacity() / 2 != 0 )
 59             resize(getCapacity() / 2);
 60 
 61         return ret;
 62     }
 63 
 64     @Override
 65     public E getFront(){
 66         if (isEmpty())
 67             throw new IllegalArgumentException("Cannot dequeue from an empty queue");
 68 
 69         return data[front];
 70     }
 71 
 72     private void resize(int newCapacity){
 73         E[] newData = (E[])new Object[newCapacity + 1];
 74         for (int i = 0; i < size; i++){
 75             //把旧的数组的首元素 放入到新的元素中 ,这里不用i,因为i不一定是首位元素
 76             newData[i] = data[(front + i) % data.length];
 77         }
 78 
 79         data = newData;
 80         front = 0;
 81         tail = size;
 82     }
 83 
 84     //覆盖父类
 85     @Override
 86     public String toString() {
 87         StringBuilder res = new StringBuilder();
 88         res.append(String.format("Queue:size = %d,capacity = %d\n", size, getCapacity()));
 89         res.append("front [");
 90         for (int i = front; i != tail; i = (i + 1) % data.length){
 91             res.append(data[i]);
 92             if ((i + 1) % data.length != tail)
 93                 res.append(", ");
 94         }
 95         res.append("] tail");
 96 
 97         return res.toString();
 98     }
 99 
100 }

 

posted on 2018-08-13 12:03  睡着的糖葫芦  阅读(251)  评论(0编辑  收藏  举报