我的算法日志:数据结构之顺序队列与循环队列

  • 队列是一种操作受限制的线性结构,遵循“先进先出”原则,即遵循FIFO(First In First Out)原则。
  • 换而言之,队列只允许在其前端(head)进行删除操作(出队),而在其后端(tail)进行插入操作(入队)。进行插入操作的端称为队尾,进行删除操作的端称为队头。

顺序队列

顺序队列是基于数组实现的, 即在连续存储单元中存放队列的元素,并设置head指示器指示队头,tail指示队尾。
每次在队尾插入一个元素是,tail增1(tail++);而每次在队头删除一个元素时,head增(head++)。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。
但是这种设定容易出现“假溢出”现象:由于入队和出队操作中,头尾指示器只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于队尾指示器已超越向量空间的上界而不能做入队操作。

循环队列

解决“假溢出”的方法是将顺序队列改为首尾相接的循环结构,这种队列就是所谓的循环队列,又称顺序循环队列。
具体操作是:无论插入或删除,一旦队尾指示器tail增1或队头指示器head增1 时超出了所分配的队列空间(capacity),就让它指向这片连续空间的起始位置。
即队头指示器head增1的操作修改为:head = (head+1)%capacity
即队尾指示器tail增1的操作修改为:tail = (tail+1)%capacity

除此之外,我们还可以用一个变量size来记录队列的长度,然后通过size和capacity(容量)的组合来判断队列的状态。

Java代码实现循环队列:
package com.guohao.arithmetics;

import java.lang.reflect.Array;

/**
 * 循环顺序队列
 */
public class SeqQueue<T> {
    private T[] dataArray;  //存放数据的数组
    private int capacity;  //队列的容量
    private int size;  //队列的长度
    private int head;  //队头元素的下标
    private int tail;  //队尾元素的下标


    public SeqQueue(Class<T> type, int capacity){
        //为了保证类型安全,Java中不允许直接用泛型声明数组,如:"dataArray = new T[capacity]"是错误的!
        dataArray = (T[]) Array.newInstance(type, capacity);

        this.capacity = capacity;
        size = 0;
        head = 0;
        tail = -1;
    }

    /**
     * 入队
     * @param element
     * @return
     */
    public boolean Enqueue(T element){
        if(!isFull()){
            tail = (tail+1)%capacity;
            dataArray[tail] = element;
            size++;
            return true;
        }

        return false;
    }

    /**
     * 出队
     * @return
     */
    public boolean Dequeue(){
        if(!isEmpty()){
            head = (head+1)%capacity;
            size--;
        }

        return false;
    }

    /**
     * 取队头元素
     * @return
     */
    public T peekHeadElement(){
        if(!isEmpty()){
            return dataArray[(head+1)%capacity];
        }

        return null;
    }

    /**
     * 判断是否满队
     * @return
     */
    public boolean isFull(){
        return size==capacity;
    }

    /**
     * 判断是否空队
     * @return
     */
    public boolean isEmpty(){
        return size==0;
    }

    //getter & setter
    public T[] getDataArray() {
        return dataArray;
    }

    public void setDataArray(T[] dataArray) {
        this.dataArray = dataArray;
    }

    public int getCapacity() {
        return capacity;
    }

    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getHead() {
        return head;
    }

    public void setHead(int head) {
        this.head = head;
    }

    public int getTail() {
        return tail;
    }

    public void setTail(int tail) {
        this.tail = tail;
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值