队列(使用数组模拟队列)

队列

队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作
简而言之,就是遵循先入先出原则。

数组模拟队列

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

数组模拟队列思路

队列本身是有序列表,使用数组的结构来存储队列的数据
因为队列的输出、输入是分别从头部尾部来处理,因此需要两个变量 front 和 rear 分别记录队列头部尾部的下标,front 会随着数据输出而改变,而 rear 则是随着数据的输入而改变

代码实现

public class ArrayQueue{
	private int maxSize;//最大容量
	private int front;//头指针
	private int rear;//尾指针
	private int[] arr;//底层数组
	
	public ArrayQueue(int maxSize){
		this.maxSize = maxSize;
		arr = new int[maxSize];
		this.front == -1;
		this.rear == -1
	}
	
	//判断队列是否已满
	public boolean isFull(){
		return rear == manSize - 1;
	}
	
	//添加元素
	public addQueue(int n){
		//先判断队列满了没
		if(isFull()){
			throw new RuntimeException("队列已满");
		}
		rear++;//尾指针+1
		arr[rear] = n;//赋值
	}
	//判断队列是否为空
	public boolean isEmpty(){
		return rear == front;
	}
}
	//取数据
	public int get(){
		if(isEmpty()){
			throw new RuntimeException("队列为空,不能取数据");
		}
		front++;
		return arr[front];
	}

	//显示队列的所有数据
    public void showQueue(){
        //判断队列是否空
        if (isEmpty()) {
            //通过抛出异常
            throw new RuntimeException("队列为空,不能取数据!");
        }
        for (int i = 0;i<arr.length;i++) {
            System.out.printf("arr[%d] = %d\n",i,arr[i]);
        }
    }

    //显示队列的头数据,注意不是取出数据
    public int headQueue(){
        //判断是否为空
        if (isEmpty()) {
            //通过抛出异常
            throw new RuntimeException("队列为空,不能取数据!");
        }
        return arr[front + 1];
    }

思考问题

此队列有以下问题

  1. 数组不能得到充分利用,使用了一次就不能复用
  2. 将这个数组使用算法,改进成一个环形数组 取模 %

数组模拟环形队列

优化思路

  1. front变量的含义做一个调整 front指向队列的第一个元素,也就是说arr[front] 就说队列的第一个元素,front的初始值=0
  2. rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值=0
  3. 当队列满时,条件是 (rear+1)% maxSize = front【满】

代码实现


/**
 * 使用数组模拟队列-编写一个ArrayQueue类
 */
class CircleArray {
    /**
     * 表示数组的最大容量
     */
    private int maxSize;
    /**
     * front变量的含义做一个调整 front指向队列的第一个元素,
     *      也就是说arr[front] 就说队列的第一个元素,front的初始值=0
     */
    private int front;
    /**
     * rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,
     *      因为希望空出一个空间作为约定,rear的初始值=0
     */
    private int rear;
    /**
     * 用于存放数据,模拟队列
     */
    private int[] arr;

    /**
     * 创建队列的构造器
     */
    public CircleArray(int arrManSize){
        maxSize = arrManSize;
        arr = new int[maxSize];
    }

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

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

    /**
     * 添加数据到队列
     */
    public void addQueue(int n){
        //判断队列是否满
        if(isFull()) {
            throw new RuntimeException("队列已满,不能加了!");
        }
        //让rear后移
        arr[rear] = n ;
        rear = (rear+1) % maxSize;
    }

    /**
     * 出队列
     */
    public int getQueue(){
        //判断队列是否空
        if (isEmpty()) {
            //通过抛出异常
            throw new RuntimeException("队列为空,不能取数据!");
        }
        //这里需要分析出 front 是指向队列的第一个元素
        //1、先把 front 对应的值保存在一个临时变量
        //2、将 front 后移
        //3、将临时保存的变量返回
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    /**
     * 显示队列的所有数据
     */
    public void showQueue(){
        //判断队列是否空
        if (isEmpty()) {
            //通过抛出异常
            throw new RuntimeException("队列为空,不能取数据!");
        }
        //思路:从front开始遍历,遍历多少个元素
        //
        for (int i = front;i<front+size();i++) {
            System.out.printf("arr[%d] = %d\n",i%maxSize,arr[i%maxSize]);
        }
    }

    /**
     * 求出当前队列有效数据的个数
     */
    public int size(){
        //rear = 1
        //front = 2
        //maxsize = 3

        return (rear + maxSize - front) % maxSize;
    }

    /**
     * 显示队列的头数据,注意不是取出数据
     */
    public int headQueue(){
        //判断是否为空
        if (isEmpty()) {
            //通过抛出异常
            throw new RuntimeException("队列为空,不能取数据!");
        }
        return arr[front];
    }

}

你可能感兴趣的:(java)