好玩的数据结构与算法————数组实现队列和循环队列

队列:

  1. 队列是一个有序列表,可以用数组或是链表来实现。
  2. 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
    单向队列:
    在这里插入图片描述
    front:指向队列头部,front是指向队列头部的前一个位置
    rear:指向队列尾的数据
    当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:思路分析
  1. 将尾指针往后移:rear+1 , 当 front == rear 【空】
  2. 若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。
    rear == maxSize - 1[队列满]

单向队列实现

public class ArrayQueue {

    /**
     * 队列头
     */
    private int front;

    /**
     * 队列尾
     */
    private int rear;

    /**
     * 数组最大容量
     */
    private int maxsize;

    /**
     * 该数据用于存放数据,模拟队列
     */
    private int [] arr;

    public int getFront() {
        return front;
    }

    public void setFront(int front) {
        this.front = front;
    }

    public int getRear() {
        return rear;
    }

    public void setRear(int rear) {
        this.rear = rear;
    }

    public int getMaxsize() {
        return maxsize;
    }

    public void setMaxsize(int maxsize) {
        this.maxsize = maxsize;
    }

    public int[] getArr() {
        return arr;
    }

    public void setArr(int[] arr) {
        this.arr = arr;
    }

    /**
     * @Description: ArrayQueue 队列构造器
     * @param: [maxsize]
     * @return:
     * @auther: zqq
     * @date: 20/5/18 18:13
     */
    public ArrayQueue(int maxsize) {
        // 指向队列头部,front是指向队列头部的前一个位置
        this.front = -1;
        // 指向队列尾的数据
        this.rear = -1;
        this.maxsize = maxsize;
        this.arr = new int[maxsize];
    }

    /**
     * @Description: isEmpty 判断是否为空
     * @param: []
     * @return: boolean
     * @auther: zqq
     * @date: 20/5/18 18:36
     */
    public boolean isEmpty(){
        return this.getFront() == this.getRear();
    }

    /**
     * @Description: isFull 判断队列是否已满
     * @param: []
     * @return: boolean
     * @auther: zqq
     * @date: 20/5/18 18:36
     */
    public boolean isFull(){
        return this.getRear() == this.getMaxsize() -  1;
    }

    /**
     * @Description: addQueue 向队列添加数据
     * @param: [n]
     * @return: void
     * @auther: zqq
     * @date: 20/5/18 18:21
     */
    public void addQueue(int n){
        if (isFull()){
            System.out.println("队列已满");
            return;
        }
        this.setRear(this.getRear()+1);
        this.arr[this.getRear()] = n;
    }

    /**
     * @Description: getQueue 出队列
     * @param: []
     * @return: int
     * @auther: zqq
     * @date: 20/5/18 18:37
     */
    public int getQueue() throws Exception {
        if (isEmpty()){
            System.out.println("队列为空");
            throw new RuntimeException("队列为空");
        }
        this.setFront(this.getFront()+1);
        return this.getArr()[this.getFront()];
    }

    /**
     * @Description: showQueue 展示队列
     * @param: []
     * @return: void
     * @auther: zqq
     * @date: 20/5/18 18:37
     */
    public void showQueue(){
        if (isEmpty()){
            System.out.println("队列为空");
            return;
        }
        for (int i = 0; i < this.getArr().length; i++) {
            System.out.printf("arr[%d] = %d\n", i, this.getArr()[i]);
        }
    }

    /**
     * @Description: headQueue 查看队列头部
     * @param: []
     * @return: int
     * @auther: zqq
     * @date: 20/5/18 18:37
     */
    public int headQueue(){
        if (isEmpty()){
            System.out.println("队列为空,没有任何数据");
            throw new RuntimeException("对内为空");
        }
        int i = this.getArr()[this.getFront()+1];
        return i;
    }
}

测试代码

public class TestQueue {
    public static void main(String[] args) {
        ArrayQueue arrayQueue = new ArrayQueue(3);
        char key = ' ';
        Scanner scanner = new Scanner(System.in);
        boolean bool = true;
        while (bool){
            System.out.println("s(show):显示队列");
            System.out.println("e(exit):推出程序");
            System.out.println("a(add):添加数据到队列");
            System.out.println("g(get):从对内取出数据");
            System.out.println("h(head):查看队列头的数据");
            key = scanner.next().charAt(0);
            switch (key){
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("请输入一个数");
                    int v = scanner.nextInt();
                    arrayQueue.addQueue(v);
                    break;
                case 'g':
                    try {
                        int queue = arrayQueue.getQueue();
                        System.out.printf("取出来的数据是 %d\n ", queue);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case 'h':
                    try {
                        int queue = arrayQueue.headQueue();
                        System.out.printf("队列头数据是 %d\n ", queue);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case 'e':
                    scanner.close();
                    bool = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出~~~");
    }
}

循环队列

单向队列出队之后有空间浪费,解决方法是让队列进行循环。
思路:
思路如下:

  1. front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
    front 的初始值 = 0
  2. rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
    rear 的初始值 = 0
  3. 当队列满时,条件是 (rear + 1) % maxSize == front 【满】
  4. 对队列为空的条件, rear == front 空
  5. 当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize // rear = 1 front = 0
  6. 我们就可以在原来的队列上修改得到,一个环形队列

代码实现:

public class CircleArrayQueue {
    /**
     * 队列头
     */
    private int front;

    /**
     * 队列尾
     */
    private int rear;

    /**
     * 数组最大容量
     */
    private int maxsize;

    /**
     * 该数据用于存放数据,模拟队列
     */
    private int [] arr;

    public int getFront() {
        return front;
    }

    public void setFront(int front) {
        this.front = front;
    }

    public int getRear() {
        return rear;
    }

    public void setRear(int rear) {
        this.rear = rear;
    }

    public int getMaxsize() {
        return maxsize;
    }

    public void setMaxsize(int maxsize) {
        this.maxsize = maxsize;
    }

    public int[] getArr() {
        return arr;
    }

    public void setArr(int[] arr) {
        this.arr = arr;
    }

    /**
     * @Description: ArrayQueue 队列构造器
     * @param: [maxsize]
     * @return:
     * @auther: zqq
     * @date: 20/5/18 18:13
     */
    public CircleArrayQueue(int maxsize) {
        // front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
        this.front = 0;
        // rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
        this.rear = 0;
        this.maxsize = maxsize;
        this.arr = new int[maxsize];
    }

    /**
     * @Description: isEmpty 判断是否为空
     * @param: []
     * @return: boolean
     * @auther: zqq
     * @date: 20/5/18 18:36
     */
    public boolean isEmpty(){
        return this.getFront() == this.getRear();
    }


    /**
     * @Description: isFull 判断队列是否已满
     * @param: []
     * @return: boolean
     * @auther: zqq
     * @date: 20/5/18 18:36
     */
    public boolean isFull(){
        return (this.getRear() +1) % this.getMaxsize() == this.getFront();
    }

    public void addQueue(int n){
        if (isFull()){
            System.out.println("队列已满");
            return;
        }
        this.getArr()[this.getRear()] = n;
        this.setRear((this.getRear()+1) % this.getMaxsize());
    }

    public int getQueue() throws Exception {
        if (isEmpty()){
            System.out.println("队列为空");
            throw new RuntimeException("队列为空");
        }
        int value = this.getArr()[this.getFront()];
        this.setFront(this.getFront()+1 % this.getMaxsize());
        return value;
    }

    public void showQueue(){
        if (isEmpty()){
            System.out.println("队列为空");
            return;
        }
        for (int i = this.getFront(); i < this.getFront()+size(); i++) {
            System.out.printf("arr[%d] = %d\n", i % (this.getMaxsize()-1), this.getArr()[i % (this.getMaxsize()-1)]);
        }
    }

    public int size(){
        return (this.getRear() + this.getMaxsize() - this.getFront()) % this.getMaxsize();
    }

    public int headQueue(){
        if (isEmpty()){
            System.out.println("队列为空,没有任何数据");
            throw new RuntimeException("对内为空");
        }
        int i = this.getArr()[this.getFront()];
        return i;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章