zoukankan      html  css  js  c++  java
  • 手写数据结构-基于动态数组的循环队列

    1.循环队列

    在基于动态数组的队列中我们发现,在移出队首元素时时间复杂度为O(n),为了解决这个问题,我们引出了循环队列。

    实现原理:双指针,多维护一个指针指向队首,当队首元素移出时,基于数组实现的队列中的元素不需要全部向前移动一个位置,只需要指向下一个元素。

    2.手动实现基于动态数组的循环队列及复杂度分析和基于动态数组的普通队列对比

    package com.tc.javabase.datastructure.array.queue;
    
    import com.tc.javabase.datastructure.queue.Queue;
    
    /**
     * @Classname LoopQueue
     * @Description 基于静态数组的循环队列
     *
     *   采用头指针和尾指针的方式实现基于静态数组的循环队列
     *   当队列为空时 和 队列满时 front = tail ,通过size == 0 区别两种情况
     *
     * 时间复杂度分析:
     *  入队:O(1)
     *  出队:O(1)
     *  查询队首元素:O(1)
     *
     *   对比: 在和基于动态数组实现的队列,在10w条数据入队出队的测试下
     *      基于动态数组实现的队列耗时:9s
     *      循环队列:0.06
     *
     *       所以循环队列性能优于基于动态数组实现的队列
     *
     * @Date 2020/7/17 09:39
     * @Created by zhangtianci
     */
    public class LoopQueue<E> implements Queue<E> {
        private E[] data;
        private int size;
        private int front;  //  指向队首的地址
        private int tail;    // 指向下一个元素存放的地址
    
        /**
         * 默认队列的容量为8
         */
        public LoopQueue() {
            this.data = (E[])new Object[8];
            size = 0;
            front = 0;
            tail = 0;
        }
    
        /**
         * @param capacity 初始化队列的容量
         */
        public LoopQueue(int capacity){
            this.data = (E[])new Object[capacity];
            size = 0;
            front = 0;
            tail = 0;
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        @Override
        public boolean isEmpty() {
            return size == 0 ? true : false;
        }
    
        /**
         *   入队
         *
         *   时间复杂度分析:O(1)
         *   即使在扩容的时候,入队n+1个元素,会有2n+1次操作,平均一个入队元素为2次操作,
         *   所以均摊复杂度也为O(1)
         * @param e
         */
        @Override
        public void enqueue(E e) {
            //考虑边界情况
            //1。队列的容量满了 扩容
            if (size == data.length){
                resize(data.length * 2);
            }
    
            data[tail] = e;
            tail = (tail + 1) % data.length;
            size++;
        }
    
        /**
         *  扩容/缩容
         * @param capacity
         */
        private void resize(int capacity){
            E[] newdata = (E[])new Object[capacity];
            for (int i = 0;i < size;i++){
                newdata[i] = data[(front + i) % data.length];
            }
    
            data = newdata;
            front = 0;
            tail = size;
        }
    
        /**
         * 出队
         * 时间复杂度分析:O(1)
         *
         * @return
         */
        @Override
        public E dequeue() {
            //考虑边界情况
            //队列为空 不能出队
            if (isEmpty()){
                throw new IllegalArgumentException("队列为空 不能出队!");
            }
    
            E e = data[front];
            data[front] = null;
            front = (front + 1) % data.length;
            size--;
    
            //缩容
            if (size == data.length / 4 && data.length / 2 != 0){
                resize(data.length / 2);
            }
    
            return e;
        }
    
        /**
         * 获取队首元素
         *
         * 时间复杂度分析:O(1)
         * @return
         */
        @Override
        public E getFront() {
            return data[front];
        }
    
        @Override
        public String toString() {
    
            StringBuilder res = new StringBuilder();
            res.append(String.format("Queue: size = %d , capacity = %d
    ", size,data.length));
            res.append("front = " + front + " [");
    
            for (int i = 0;i < size;i++){
                res.append(data[(front + i) % data.length]);
                if ((front + i + 1) % data.length != tail){
                    res.append(", ");
                }
            }
            res.append("] " +  "tail=" + tail);
            return res.toString();
        }
    
        public static void main(String[] args) {
    
            LoopQueue<Integer> queue = new LoopQueue<>();
            for(int i = 0 ; i < 100 ; i ++){
                queue.enqueue(i);
                System.out.println(queue);
    
                if(i % 3 == 2){
                    queue.dequeue();
                    System.out.println(queue);
                }
            }
        }
    }
    
  • 相关阅读:
    remove &#39;^M&#39; in shell script
    MyBatis学习总结——实现关联表查询(转)
    SSM框架下结合 log4j、slf4j打印日志
    intellij IDEA里各图标对应的文件类型
    springboot整合shiro
    在Eclipse中如何关联源代码
    windows7 创建http 服务器
    Intellij IDEA 安装和配置jrebel进行项目的热部署
    IntelliJ IDEA 热部署插件 JRebel 安装激活及使用
    idea 安装热部署插件
  • 原文地址:https://www.cnblogs.com/tc971121/p/13443634.html
Copyright © 2011-2022 走看看