美文网首页
队列(Queue)

队列(Queue)

作者: 代夫阿普曼 | 来源:发表于2019-06-22 20:26 被阅读0次

    队列是一种先进先出的线性数据结构。

    队列的主要操作的是入队和出队,需要从一端进入,从另外一端出去。

    • Queue接口定义

      public interface Queue<E> {
          int getSize();
          boolean isEmpty();
          void enqueue(E e);  //入队
          E dequeue();        //出队
          E getFront();       //获取队首元素
      }
      
    • 队列可以使用数组实现,也可以使用链表实现

      //使用数组实现
      public ArrayQueue<E> implements Queue<E> {
          
          private Array<E> array;
          public ArrayQueue(int capacity) {
              array = new Array<>(capacity);
          }
          public ArrayQueue() {
              array = new Array<>();
          }
          
          public int getSize() {
              return array.getSize();
          }
          
          public boolean isEmpty() {
              return array.isEmpty();
          }
          
          public void enqueue(E e) {
              array.addLast(e);
          }
          
          public E dequeue() {
              return array.removeFirst();
          }
          
          public E getFront() {
              return array.getFirst();
          }
          
      }
      
      //使用链表实现
      public class LinkedListQueue<E> implements Queue<E> {
      
          //定义链表的节点
          private class Node {
              private E e;
              private Node next;
      
              public Node(E e, Node next) {
                  this.e = e;
                  this.next = next;
              }
              public Node(E e) {
                  this(e, null);
              }
              @Override
              public String toString() {
                  return e.toString();
              }
          }
      
          private Node head, tail;
          private int size = 0;
      
          public LinkedListQueue() {
              head = null;
              tail = null;
              size = 0;
          }
      
          @Override
          public int getSize() {
              return size;
          }
      
          @Override
          public boolean isEmpty() {
              return size == 0;
          }
      
          @Override
          public void enqueue(E e) {
              //由于没有设置dummyHead,当链表为空就需要单独处理
              if(tail == null) {
                  tail = new Node(e);
                  head = tail;
              } else {
                  tail.next = new Node(e);
                  tail = tail.next;
              }
              size ++;
          }
      
          @Override
          public E dequeue() {
              if(isEmpty()){
                  throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
              }
              Node retNode = head;
              //head指针后移
              head = head.next;
              retNode.next = null;
              if(head == null) {
                  tail = null;
              }
              size --;
              return retNode.e;
          }
      
          @Override
          public E getFront() {
              if(isEmpty()){
                  throw new IllegalArgumentException("Empty Queue.");
              }
              return head.e;
          }
      
          @Override
      public String toString() {
          StringBuilder res = new StringBuilder();
          res.append("Queue: (front)");
      
          Node curr = head;
          while(curr != null) {
              if(curr.next != null) {
                  res.append(curr + "->");
              }else{
                  res.append(curr + "(tail) -> ");
              }
              curr = curr.next;
          }
          res.append("null");
          return res.toString();
      }
      }
      
    • 循环队列

      正是因为循环队列在元素出队操作的优化(数组队列的出队操作,需要将剩余元素全部前移),才使得循环队列的复杂度大大降低。

      public class LoopQueue<E> implements Queue<E> {
      
          private E[] data;
          private int front, tail;
          private int size;
      
          public LoopQueue(int capacity) {
              //容量+1,是因为我们要故意浪费一个空间
              data = (E[]) new Object[capacity + 1];
              front = 0;
              tail = 0;
              size = 0;
          }
      
          public LoopQueue() {
              this(10);
          }
      
          @Override
          public int getSize() {
              return size;
          }
      
          public int getCapacity() {
              return data.length-1;
          }
      
          @Override
          public boolean isEmpty() {
              return front == size;
          }
      
          @Override
          public void enqueue(E e) {
              //判断是否堆满
              if( (tail+1)%data.length == front) {
                  resize(getCapacity() * 2);
              }
      
              //元素入队
              data[tail] = e;
              //tail循环后移
              tail = (tail+1)%data.length;
              size ++;
          }
      
          private void resize(int newCapacity) {
              E[] newData = (E[]) new Object[newCapacity + 1];
              for (int i = 0; i < size; i++) {
                  newData[i] = data[(i+front)%data.length];
              }
              data = newData;
              front = 0;
              tail = size;
          }
      
          @Override
          public E dequeue() {
              //队列是否为空
              if(isEmpty()) {
                  throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
              }
      
              E ret = data[front];
              data[front] = null;
              front = (front+1)%data.length;
              size --;
      
              //动态缩容
              if(size == getCapacity() / 4 && getCapacity() /2 != 0) {
                  resize(getCapacity() / 2);
              }
      
              return ret;
          }
      
          @Override
          public E getFront() {
              //队列是否为空
              if(isEmpty()) {
                  throw new IllegalArgumentException("Queue is empty.");
              }
              return data[front];
          }
      
          @Override
          public String toString() {
              StringBuilder res = new StringBuilder();
              res.append(String.format("LoopQueue:size = %d, capacity = %d\n", size, getCapacity()));
              res.append("front-> [");
              for (int i = front; i != tail ; i = (i+1)%data.length) {
                  res.append(data[i]);
                  if((i+1)%data.length != tail) {
                      res.append(", ");
                  }
              }
              res.append("] <-tail\n");
              return res.toString();
          }
      }
      

    相关文章

      网友评论

          本文标题:队列(Queue)

          本文链接:https://www.haomeiwen.com/subject/cjovqctx.html