队列的实现方式

      1. 数组模拟队列实现
  • 顺序队列的实现

以下采用数组实现,初始化一个队列数组的空间长度为5,队列有两个标记,一个队头的位置front,一个队尾的位置rear,初始都指向数组下标为0的位置,如图所示:

在插入元素时,rear标记递增+1,比如依次入队11,22,33这三个元素,则当前队列存储情况如图:

当前front为0,rear为3,接下来执行出队操作,此处将11元素出队,则front标记递增+1,此时队列的存储情况如图:

根据上面的图例,我们可以通过rear-front获得队列中元素的个数。当”front==rear”时,此时队列为空,而当”rear==数组长度”时,此时将无法添加元素,我们可以设为队列已满,接下来我们就通过代码实现这个操作。

【示例】顺序队列的实现

public class ArrayQueue<T> {

    /**

     * 模拟队列的数组

     */

    private Object[] elementData;

    /**

     * 保存队首的指针

     */

    private int front;

    /**

     * 保存队尾的指针

     */

    private int rear;

    /**

     * 无参构造方法

     */

    public ArrayQueue() {

        // 设置数组的默认空间长度为10

        this(10);

    }

  

    /**

     * 有参构造方法

     * @param capcaity 设置数组的空间长度

     */

    public ArrayQueue(int capcaity) {

        // 处理capcaity参数不合法的情况

        if (capcaity < 0) {

            throw new IllegalArgumentException("参数不合法异常,capcaity" + capcaity);

        }

        // 创建指定空间长度的数组

        this.elementData = new Object[capcaity];

    }


      /**

     * 获取队列中元素的个数

       * @return 返回队列中元素的个数

     */

    public int getSize() {

        return rear - front;

      }


    /**

     * 队列操作

     * @param element

     */

    public void add(T element) {

        // 判断队列是否已满

        if (isFull()) {

            throw new RuntimeException("队列已满,无法执行入队列操作");

        }

        // 执行入队操作

        elementData[rear++] = element;

    }

  

    /**

     * 删除队列的首元素

     * @return 返回被删除的元素值

     */

    public T remove() {

        // 判断队列是否为空

        if (isEmpty()) {

            throw new RuntimeException("队列为空,无法执删除队列操作");

        }

        // 获取队列首元素

        T element = (T)elementData[front];

        // front索引位置元素设置为默认值,并更新front索引值

        elementData[front++] = null;

        // 返回被删除的队首元素

        return element;

    }

  

    /**

     * 获得队列的首元素

     * @return 返回队列的首元素

     */

    public T element() {

        // 判断队列是否为空

        if (isEmpty()) {

            throw new RuntimeException("队列为空,无法执获取队列操作");

        }

        // 获取并返回队列的首元素

        return (T)elementData[front];

    }

  

    /**

     * 判断队列是否已满

     * @return 队列已满,则返回true;队列未满,则返回false。

     */

    private boolean isFull() {

        return rear == elementData.length;

    }

  

    /**

     * 判断队列是否为空

     * @return 队列为空,则返回true;队列不为空,则返回false。

     */

    public boolean isEmpty() {

        return front == rear;

    }

}

按照以上的操作,当front==rear时,那么队列是否已经满呢?未必!因为front和rear在入队和出队操作中只增不减,因此head和tail都会最终指向队列之外的存储位置,此时虽然数组为空,但也无法将元素入队。

如何解决这个问题,我们引入了循环队列。当rear的取值为数组空间长度,此时如果数组还有空闲的位置,将rear重新指向数组的0索引处即可,如图所示:

如果继续入队66和77这两个元素,则队列的存储结构如图:

在采用循环队列实现的过程中,当队列满队时,front等于rear,而当队列空时,front也等于rear,为了区分两种状态,一般规定循环队列的长度为”数组长度-1”,即有一个位置不放元素,此时front==rear时为空队,而当front==(rear+1)%数组长度,说明对满。

【示例】循环队列的实现

public class ArrayQueue<T> {

    /**

     * 模拟队列的数组

     */

    private Object[] elementData;

    /**

     * 保存队首的指针

     */

    private int front;

    /**

     * 保存队尾的指针

     */

    private int rear;

    /**

     * 无参构造方法

     */

    public ArrayQueue() {

        // 设置数组的默认空间长度为10

        this(10);

    }

  

    /**

     * 有参构造方法

     * @param capcaity 设置数组的空间长度

     */

    public ArrayQueue(int capcaity) {

        // 处理capcaity参数不合法的情况

        if (capcaity < 0) {

            throw new IllegalArgumentException("参数不合法异常,capcaity" + capcaity);

        }

        // 创建指定空间长度的数组

        this.elementData = new Object[capcaity];

    }

  

    /**

     * 获取队列中元素的个数

     * @return 返回队列中元素的个数

     */

    public int getSize() {

        if (rear >= front) {

            return rear - front;

        }

        else {

            return (rear + elementData.length) - front;

        }

    }

  

    /**

     * 入栈操作

     * @param element

     */

    public void add(T element) {

        // 判断队列是否已满

        if (isFull()) {

            throw new RuntimeException("队列已满,无法执行入队列操作");

        }

        // 执行入队操作

        elementData[rear] = element;

        // 更新rear的值

        rear = (rear + 1) % elementData.length;

    }

  

    /**

     * 删除队列的首元素

     * @return 返回被删除的元素值

     */

    public T remove() {

        // 判断队列是否为空

        if (isEmpty()) {

            throw new RuntimeException("队列为空,无法执删除队列操作");

        }

        // 获取队列首元素

        T element = (T)elementData[front];

        // front索引位置元素设置为默认值

        elementData[front] = null;

        // 更新front索引值

        front = (front + 1) % elementData.length;

        // 返回被删除的队首元素

        return element;

    }

  

    /**

     * 获得队列的首元素

     * @return 返回队列的首元素

     */

    public T element() {

        // 判断队列是否为空

        if (isEmpty()) {

            throw new RuntimeException("队列为空,无法执获取队列操作");

        }

        // 获取并返回队列的首元素

        return (T)elementData[front];

    }

  

    /**

     * 判断队列是否已满

     * @return 队列已满,则返回true;队列未满,则返回false。

     */

    private boolean isFull() {

        return front == (rear + 1) % elementData.length;

    }

  

    /**

     * 判断队列是否为空

     * @return 队列为空,则返回true;队列不为空,则返回false。

     */

    public boolean isEmpty() {

        return front == rear;

    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值