数组模拟队列以及环形队列 学习记录

数组模拟队列以及环形队列

    • 队列
      • 队列分析
      • 代码实现
      • 问题
    • 环形队列
      • 思路分析
      • 代码实现

本文旨在加深学习印象并留记录以供日后查看。学习视频为韩顺平图解Java数据结构和算法,以下内容来自于视频内容与自我总结。如有错误请您指正。

队列

队列分析

  1. 队列是一个有序列表,可以用数组或是链表来实现。
  2. 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

示意图:(使用数组模拟队列示意图)
数组模拟队列以及环形队列 学习记录_第1张图片

  1. 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变
  2. 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变
  3. 当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤
    (1)将尾指针往后移:rear+1 , 当front == rear 表示队列为空
    (2)若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1则队列已满

代码实现

package com.hyf.queue;

public class ArrayQueueDemo {
    public static void main(String[] args) {
        //测试
        //创建队列
        ArrayQueue queue = new ArrayQueue(3);
        queue.addQueue(1);
        queue.addQueue(2);
        queue.addQueue(3);
        queue.addQueue(4);

        queue.showQueue();
        System.out.println();
        System.out.println("------------");

        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());

        System.out.println("------------");

        queue.showQueue();
    }

}

//使用数组模拟队列
class ArrayQueue {
    private int maxSize; // 数组队列的最大长度/容量
    private int front;  // 队列头位置
    private int rear;   // 队列尾位置
    private int[] arr;  // 存放队列数据

    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        this.arr = new int[this.maxSize];
        this.front = -1;
        this.rear = -1;
    }

    //判断队列是否已满
    public boolean isFull() {
//        if (this.rear >= this.maxSize-1){
//            return true;
//        }
//        return false;
        return this.rear == this.maxSize-1;
    }
    //判断队列是否为空
    public  boolean isEmpty() {
        return this.front == this.rear;
    }
    //添加数据到队列中,入队列
    public void addQueue(int a) {
        if (isFull()){
            System.out.println("队列已满");
            return;
        }
        this.rear++;
        this.arr[this.rear] = a;
    }
    //获取数据,出队列
    public int getQueue(){
        if (isEmpty()){
            throw new RuntimeException("队列为空,无数据");
        }
        this.front++;
        return this.arr[this.front];
    }
    //显示队列所有数据
    public void showQueue(){
        if (isEmpty()){
            System.out.println("队列为空,无数据");
            return;
        }
        for (int i = 0; i < this.arr.length; i++) {
            System.out.printf("%d\t", this.arr[i]);
        }
    }
}

问题

目前的数组只能使用一次,不能复用。

环形队列

为了充分利用数组,可以考虑将数组改造为一个环形的

思路分析

  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

代码实现

将之间的代码做一些修改

package com.hyf.queue;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {
        //测试
        //创建环形队列
        //设置长度4, 其队列的有效数据最大是3
        CircleArrayQueue queue = new CircleArrayQueue(4);
        queue.addQueue(11);
        queue.addQueue(22);
        queue.addQueue(33);
        queue.addQueue(44);
        //显示队列所有数据
        queue.showQueue();
        System.out.println();
        System.out.println("------------");

        //取一个,再加一个55
        System.out.println(queue.getQueue());
        queue.addQueue(55);
        queue.showQueue();
        System.out.println();
        System.out.println("-----------");

        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());
        queue.addQueue(66);
        queue.showQueue();
        System.out.println();
        System.out.println("------------");

        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());
        System.out.println(queue.getQueue());

    }
}

class CircleArrayQueue {
    private int maxSize; // 数组队列的最大长度/容量
    //front 指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
    //初始值 = 0
    private int front;  // 队列头位置
    //rear 指向队列的最后一个元素的后一个位置
    //初始值 = 0
    private int rear;   // 队列尾位置
    private int[] arr;  // 存放队列数据


    public CircleArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        this.arr = new int[this.maxSize];
    }

    //判断队列是否已满
    public boolean isFull() {
        return (this.rear + 1) % this.maxSize == this.front;
    }

    //判断队列是否为空
    public  boolean isEmpty() {
        return this.front == this.rear;
    }

    //添加数据到队列中,入队列
    public void addQueue(int a) {
        if (isFull()){
            System.out.println("队列已满");
            return;
        }
        //先加入
        this.arr[this.rear] = a;
        //再后移,注意环形要取模,不然会导致数组越界
        this.rear = (this.rear + 1) % this.maxSize;
    }

    //获取数据,出队列
    public int getQueue(){
        if (isEmpty()){
            throw new RuntimeException("队列为空,无数据");
        }
        //先取值
        int res = this.arr[this.front];
        //再后移,注意取模,不然会导致数组越界
        this.front = (this.front + 1) % this.maxSize;
        return res;
    }

    //显示队列所有数据
    public void showQueue(){
        if (isEmpty()){
            System.out.println("队列为空,无数据");
            return;
        }
		//此时的i不是数组下标,会造成数组越界,所以要进行取模才能作为下标取值
        for (int i = this.front; i < this.front + size(); i++) {
            System.out.printf("%d\t", this.arr[i % this.maxSize]);
        }
    }

    //获取arr中的有效元素个数
    public int size(){
        return (this.rear + this.maxSize - this.front) % this.maxSize;
    }


}

测试结果
数组模拟队列以及环形队列 学习记录_第2张图片

你可能感兴趣的:(数据结构与算法)