• [数据结构]之队列


    1. 概述

      • 队列对应的操作是数组的子集
      • 只能从一端(队尾)添加元素,只能从另一端(队首)删除元素
      • 先进先出(FIFO:First In First Out)

    2. 队列的实现

    队列的接口定义

    代码实现:

    package com.ytuan.queue;
    
    public interface Queue<E> {
    
        public void enqueue(E e);
        
        public E dequeue();
        
        public boolean isEmpty();
        
        public int getSize();
        
        public E getFront();
    }

     数组队列:

    在这里会使用之前实现的动态数组,参考地址:https://www.cnblogs.com/ytuan996/p/10692548.html

     代码实现:

    package com.ytuan.queue;
    
    import com.ytuan.array.Array;
    
    public class ArrayQueue<E> implements Queue<E> {
    
        private Array<E> array;
    
        public ArrayQueue(int capacity) {
            array = new Array<>(capacity);
        }
    
        public ArrayQueue() {
            array = new Array<E>();
        }
    
        @Override
        public void enqueue(E e) {
            array.addLast(e);
        }
    
        @Override
        public E dequeue() {
            return array.removeFirst();
        }
    
        @Override
        public boolean isEmpty() {
            return array.isEmpty();
        }
    
        @Override
        public int getSize() {
            return array.getSize();
        }
    
        @Override
        public String toString() {
    
            StringBuffer res = new StringBuffer();
    
            res.append(String.format("Queue size = %d, capacity = %d.  
    ", array.getSize(), array.getCapacity()));
    
            res.append("front [");
    
            for (int i = 0; i < array.getSize(); i++) {
                res.append(array.get(i));
                if (i != array.getSize() - 1)
                    res.append(',');
            }
    
            res.append("] end");
            return new String(res);
        }
    
        @Override
        public E getFront() {
            return array.getFirst();
        }
    
    }
    View Code

    循环队列:

      在数组队列的实现中,对于dequeue(出队)的时间复杂度是O(n)级别的,而循环队列是解决这一问题的方案。它使用两个之指针分别表示队列的队首和队尾,在整个数组中循环改变,多使用一个空间来维护这两个指针的关系。示意如图:

     代码实现:

    package com.ytuan.queue;
    
    public class LoopQueue<E> implements Queue<E> {
    
        private E[] data;
    
        private int front, tail;
        private int size; // 元素个数,可以省略,使用front, tail计算得到。扩展部分
    
        public LoopQueue(int capacity) {
            data = (E[]) new Object[capacity + 1];
            front = 0;
            tail = 0;
            size = 0;
        }
    
        public LoopQueue() {
            this(10);
        }
    
        @Override
        public void enqueue(E e) {
    
            if (tail + 1 == front)
                resize(getCapacity() * 2);
    
            data[tail] = e;
            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 String toString() {
    
            StringBuffer res = new StringBuffer();
    
            res.append(String.format("Queue  size = %d, capacity = %d. 
    ", getSize(), getCapacity()));
    
            res.append("front [");
    
            for (int i = front; i != tail; i = (i + 1) % data.length) {
                res.append(data[i % data.length]);
    
                if ((i + 1) % data.length != tail)
                    res.append(',');
            }
    
            res.append("] tail");
            return new String(res);
        }
    
        @Override
        public E dequeue() {
    
            if (isEmpty())
                throw new IllegalArgumentException("can not dequeue form an Empty Queue");
    
            E res = data[front];
    
            data[front] = null;
            front = (front + 1) % data.length;
            size--;
    
            if (size == getCapacity() / 4 && getCapacity() / 2 != 0)
                resize(getCapacity() / 2);
    
            return res;
        }
    
        @Override
        public boolean isEmpty() {
            return size == 0;
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        public int getCapacity() {
            return data.length - 1;
        }
    
        @Override
        public E getFront() {
    
            if (isEmpty())
                throw new IllegalArgumentException("no element to access!");
    
            return data[front];
        }
    
    }
    View Code

  • 相关阅读:
    XSS 防御方法总结
    IE浏览器兼容方案
    js 排序算法
    webapck 打包体积优化策略
    webapck 速度优化策略
    Grunt、Gulp和Webpack对比
    数据库中的undo日志、redo日志
    使用sysbench对mysql压力测试
    java -cp & java jar的区别
    使用BenchmarkSQL测试PostgreSQL
  • 原文地址:https://www.cnblogs.com/ytuan996/p/10697396.html
Copyright © 2020-2023  润新知