队列

参考资料:《大话数据结构》

定义

队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。允许插入的一端称为队头尾,允许删除的一端称为队头。简单的说,就是我们生活中排队买票,队头的人买完离开(删除),新来的人在队尾排队买票(插入)。
在这里插入图片描述

循环队列

先来定义两个指针,一个是队头指针(front),指向队头元素,一个是队尾指针(rear),指向队尾元素的下一个位置。当队列为空时,front等于rear(刚开始下标均为0)。当一个元素出队时,元素先出队,队头指针再往后移一位,当有新元素入队时,先入队,然后队尾指针再向后移一位。然而,当队列不是循环队列时,这是有问题的。假设现在数组长度为5,rear在数组下标为4的位置,由于之前有元素出队,front现在再下标为2的位置(即下标为0和1的地方都是空的)。现在有一新元素要入队,那么新元素在下标为4的地方,之后rear后移一位,但是数组长度为5,rear此时没法往后移,但此时下标为0和1的地方明明是空的,却不能存入元素。
在这里插入图片描述
故有了循环队列。上述问题中,我们可以让rear指向下标为0的位置。我们把队列头尾相接的顺序储存结构称为循环队列
在这里插入图片描述
然而问题又来了,现在我们再往队列中加入两个新元素,则front和rear应该重合,同时指向下标为2的位置。
在这里插入图片描述
根据上面的定义,当front等于rear时,队列为空,但是此时队列并不为空。所以应该修改一下,规定队列为空的定义依然不变,当队列满时,数组还剩一个空闲单元。此时front和rear相邻,但是谁大谁小不好说(如下图)。我们发现,当数组长度为len时,满足front =(rear + 1) % len时,队列为满。如下图,front=0,rear=4,len=5,0=(4+1)%5。
在这里插入图片描述
此外,还有一个计算队列长度QueueSize的公式:QueueSize = (rear - front + len ) % len

由上面分析可得:

  1. 定义一个循环队列需要一个数组、front和rear(front和rear初始化为0)。
int queue = new int[len];  //len为数组长度
int front = 0;
int rear = 0;

2.根据上面公式判断队列是否满

 public boolean isFull(){
        if ((rear + 1) % len == front)  //队列满时,队中还有一个空位
            return true;
        else
            return false;
    }

  1. 判断队列是否为空
 public boolean isEmpty(){
        if(front == rear)
            return true;
        else
            return false;
    }

4.根据上面公式求队列长度

public int length(){
        return (rear - front + len) % len;
    }
  1. 入队,先判断队列是否满,满则不能再入队。
 public boolean enQueue(int val){
        if(isFull())
            return false;
        arr[rear] = val;  //队尾指针始终指向最后一个元素的下一个元素
        rear = (rear + 1) % len;  //队尾指针后移一位

        return true;
    }

  1. 出队,先判断队列是否为空,空则不能出队。
public boolean deQueue(){
        if(isEmpty())
            return false;
        val = arr[front];
        System.out.println(val);
        front = (front + 1) % len;  //队头指针始终指向第一个元素

        return true;
    }

队列的链式存储结构

队列的链式存储结构,就是单链表,但是只能头出尾进。我们将队头指针指向头结点,队尾指针指向终端结点。
在这里插入图片描述
当队列为空时,front和rear均指向头结点。
在这里插入图片描述
队列的入队操作相当于尾插法。
在这里插入图片描述
队列的出队操作就是把头结点的后面的结点出队,将头结点的后面结点改为出队结点的后面结点。
在这里插入图片描述
Java代码:

public class Node {

    int data;
    Node next;

    public Node(int data) {
        this.data = data;
    }
}

---------------------------------------------------------------------------------

public class Queue {

    Node front;  //队头指针
    Node rear;   //队尾指针
    Node head;   //链表的头结点
    int val;  //接收出队元素的值

    /*初始化队列*/
    public Queue() {
        head = new Node(0);
        front = head;  //刚开始队头队尾指针均指向链表的头结点,头结点的值默认为0
        rear = head;
    }

    /*判断队是否为空*/
    public boolean isEmpty(){

        if(front.next == null)
            return true;
        else
            return false;
    }

    /*入队(队尾入)*/
    public boolean enQueue(int val){

        /*链表不存在满的情况*/
        Node j = new Node(val);
        j.next = null;
        rear.next = j;
        rear = j; //队尾指针rear始终指向队尾最后一个结点

        return true;
    }

    /*出队(队头出)*/
    public boolean deQueue() throws EmptyException {

        if(isEmpty())
           return false;
       	front = front.next;  //此次出队后,队头指针指向刚刚出队的结点,下一次再出队时,队头指针先下移一位
        val = front.data;
        System.out.println(val);
        return true;
    }

    /*求队列长度*/
    public int length(){

        int len = 0;
        Node n = front;
        while (n.next != null){
            len++;
            n = n.next;
        }
        return len;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值