Live2D

新知识-Queue_循环队列

新知识-Queue(FIFO)

FIFO:First in First out; 队列:先进先出

  • 入队和出队。入队会向队列追加一个新元素,而出队会删除第一个元素,一个索引来指出起点。

代码:

/** ... 动态数组和指向起点的标志位*/
class MyQueue {
    // store elements
    private List<Integer> data;         
    //start sign
    private int p_start;            
    public MyQueue() {
        data = new ArrayList<Integer>();
        p_start = 0;
    }
    /** 插入值,返回是否成功. */
    public boolean enQueue(int x) {
        data.add(x);
        return true;
    };    
    /** 删除. */
    public boolean deQueue() {
        if (isEmpty() == true) {    /** 非空判断,空队列不能删除,返回false*/
            return false;
        }
        p_start++;	/*删除队首,指针后移*/
        return true;
    }
    /** 队首. */
    public int Front() {
        return data.get(p_start);
    }
    /** 检查非空. */
    public boolean isEmpty() {
        return p_start >= data.size();	/*队首>=长度==0  队列为空*/
    }     
};

public class Main {
    public static void main(String[] args) {
        MyQueue q = new MyQueue();		/* ...  动态数组对象建立,起点位初始化*/
        q.enQueue(5);
        q.enQueue(3);
        if (q.isEmpty() == false) {
            System.out.println(q.Front());   /* FIFO*/
        }
        q.deQueue();
        if (q.isEmpty() == false) {
            System.out.println(q.Front());
        }
        q.deQueue();
        if (q.isEmpty() == false) {
            System.out.println(q.Front());
        }
    }
}
#include <iostream>

class MyQueue {
    private:
        // store elements
        vector<int> data;       
        // a pointer to indicate the start position
        int p_start;            
    public:
        MyQueue() {p_start = 0;}
        /** Insert an element into the queue. Return true if the operation is successful. */
        bool enQueue(int x) {
            data.push_back(x);
            return true;
        }
        /** Delete an element from the queue. Return true if the operation is successful. */
        bool deQueue() {
            if (isEmpty()) {
                return false;
            }
            p_start++;
            return true;
        };
        /** Get the front item from the queue. */
        int Front() {
            return data[p_start];
        };
        /** Checks whether the queue is empty or not. */
        bool isEmpty()  {
            return p_start >= data.size();
        }
};

int main() {
    MyQueue q;
    q.enQueue(5);
    q.enQueue(3);
    if (!q.isEmpty()) {
        cout << q.Front() << endl;
    }
    q.deQueue();
    if (!q.isEmpty()) {
        cout << q.Front() << endl;
    }
    q.deQueue();
    if (!q.isEmpty()) {
        cout << q.Front() << endl;
    }
}

循环队列

  • 基础实现非常的低效,当队列排队溢满时,我们要想继续insert则需要将队首delete

  • 我们在这里引入双指针思路,在固定的数组中两个指针表示起始位置和结束位置,达到重用我们浪费的存储空间

  1. 头指针和尾指针之间实现循环的作用(环形缓冲器),利用先前使用的空间。

  2. 当front和Tail(头尾指针)都指向-1时,队列为空。

  3. insert第一位时,front和Tail都向后移一位,指向0,后面insert非第一位时,Tail单独向后移动。

  4. 当Tail指向最后一位时,通过取余%位数或者==0,返回队首,完成循环,继续插入,当Tail移动到front前面时,队列满队。

  5. 通过front往后移动完成delete,当front移动到Tail前面时,frontTail-1完成清空。

  • 自我实现代码:

    后面有标准答案,自寻,学习的话建议先粗略看一下我的过程,发现一下我的哪一步需要完善,再去看标准答案,会有柳暗花明的感觉...反面教材来一手

class MyCircularQueue {
    private int[] data;
    private int front,tail;

    public MyCircularQueue(int k) {
        data = new int[k + 1];    /**-1位导致循环队列要比数值多一位 */
        front = 0;
        tail = 0;
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }else{
            data[tail] = value;
            tail = (tail + 1) % data.length;
            return true;
        }
    }
    
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }else{
            front = (front + 1) % data.length;
            return true;
        }
    }
    
    public int Front() {
        if(isEmpty()){
            return -1;
        }else{
             return data[front];
        }   
    }
    
    public int Rear() {
        if(isEmpty()){
            return -1;
        }else{
             return data[(tail - 1 + data.length) % data.length];
        } 
    }
    
    public boolean isEmpty() {
        if(front == tail){
            return true;
        }
        return false;
    }
    
    public boolean isFull() {
        if((tail + 1)%data.length == front){
            return true;
        }
        return false;
    }
}
  • 实现循环列表错误记录:

    1. 判满的时候注意tail+1==front注意取余,不然会影响到enQueue,错误的判满导致错误的插入,

    2. 入列要判满,出列要判空,取队首尾先判空。

      3.k+1好像这个思路可有可无

标准实现

class MyCircularQueue {
    
    private int[] data;
    private int head;
    private int tail;
    private int size;

    public MyCircularQueue(int k) {
        data = new int[k];
        head = -1; 			/** ..-1起步,嗯这才是标准*/
        tail = -1;
        size = k;			/**  存放数组大小,这个地方不知道干嘛,往后看...*/
    }
    
    public boolean enQueue(int value) {
        if (isFull() == true) {
            return false;
        }
        if (isEmpty() == true) {	/**加了个判空,空意味着第一步,前面说了第一步先设0,没错*/
            head = 0;
        }
        tail = (tail + 1) % size;		//偷懒的,没事了
        data[tail] = value;/**把tail设0放在了后面,就可以变成先移动指针再设值,嗐我怎么没想到*/
        return true;
    }
    
    public boolean deQueue() {
        if (isEmpty() == true) {
            return false;
        }
        if (head == tail) {			/**谨慎的加了个清空,先前说了头尾为-1为初始化状态*/
            head = -1;
            tail = -1;
            return true;		/**属于最后一步出列,return true*/
        }
        head = (head + 1) % size;		
        return true;
    }
    
    public int Front() {
        if (isEmpty() == true) {
            return -1;
        }
        return data[head];
    }

    public int Rear() {
        if (isEmpty() == true) {
            return -1;
        }
        return data[tail];  /**这个地方就可以省略那一大步了。。。*/
    }

    public boolean isEmpty() {
        return head == -1;
    }

    public boolean isFull() {
        return ((tail + 1) % size) == head;    /**important*/
    }
}
  • 内置队列库实现:

    public class Main {
        public static void main(String[] args) {
            Queue<Integer> q = new LinkedList();		/**LinkedList*/
            System.out.println("The first element is: " + q.peek());	/*peek队首*/
            //offer入列
            q.offer(1);
            q.offer(2);
            q.offer(3);
            q.offer(123);
            //poll出列
            q.poll();
            // 队首
            System.out.println("The first element is: " + q.peek());
            // 队列长度size
            System.out.println("The size is: " + q.size());
        }
    }
    
posted @ 2021-08-12 17:00  饭耶  阅读(147)  评论(1编辑  收藏  举报