数据结构-队列

本文详细介绍了队列的基本概念,包括其线性表的实现原理、FIFO操作原则以及普通队列、双端队列和循环队列的特性。通过实例展示了如何使用链表和顺序表实现队列,并探讨了队列的入队、出队、判断空满的操作。同时,提到了优先级队列这一高级应用。

队列Queue

栈的实现原理为线性表,特点是只允许在线性表其中一端进行数据的增加操作,另一端进行删除操作,允许增加的一端为队尾(Tail/Rear),允许删除的一端称为队头(Head/Front)。

队列遵循先入先出的操作原则,即FIFO(First In First Out)。

队列的增加操作叫做入队在队尾加入数据。
队列的删除操作叫做出队在栈顶删除数据。

队列分为三种:普通队列()、双端队列、循环队列、优先级队列

常用方法

返回值方法用途
booleanempty()判断栈是否为空
Epeek()得到队头元素
Epoll()将元素出队
Eoffer(E item)将元素入队

普通队列和双端队列

普通队列Queue:只允许在其中一端进行数据的增加操作,另一端进行删除操作。

在这里插入图片描述

双端队列Deque: 队头和队尾都可以进行数据的增加和删除操作。

在这里插入图片描述
普通队列和双端队列通常建议使用链表实现,增加和删除操作的时间复杂度为O(1)。

普通队列简单实现

class Node<E>{
    public Object val;//数据
    public Node next;

    public Node(E val){
        this.val=val;
    }
}
public class MyQueue<E> {
    private Node<E> head;//队头
    private Node<E> last;//队尾
    private int usedSize;//可用元素

    /**
     * 元素入队
     * @param val
     */
    public void offer(E val){
        Node<E> node=new Node<>(val);
        if(this.head==null){
            this.head=node;
            this.last=node;
        }else {
            this.last.next=node;
            this.last=this.last.next;
        }
        this.usedSize++;
    }

    /**
     * 判断队列是否为空
     * @return
     */
    public boolean empty(){
        return this.head==null;
    }

    /**
     * 元素出队
     * @return
     */
    public E poll(){
        if(empty()){
            throw new RuntimeException("队列为空");
        }
        Object oldValue=this.head.val;
        this.head=this.head.next;
        this.usedSize--;
        return (E)oldValue;
    }
    public E peek(){
        if(empty()){
            throw new RuntimeException("队列为空");
        }
        return (E)this.head.val;
    }

    /**
     * 队列中目前元素数量
     * @return
     */
    public int size(){
        return this.usedSize;
    }
}

循环队列

循环队列: 队头和队尾相接的顺序存储结构。
在这里插入图片描述
循环队列通常使用顺序表结构来存储数据,队头front和队尾rear相接来构成循环队列。

思路:设置两个标识front和rear代表队头下标和队尾下标,当队头或队尾走到顺表最后一个位置时,将队头或队尾重新指向队列开始开始时的下标来达到循环效果。

下标循环公式:(index+offset)%顺序表的长度array.length
index:队列结束位置
offset:队列最后一个位置到队头的偏移量
array.length:顺序表的长度

判断循环队列空与满

第一种方式:循环列表设置一个变量size用来表示当前队列内元素数量,当size为0,表示队列为空,当size等于队列长度,队列为满。

第二种方式:
1.设置一个标志位flag=false。
2.每次向队列放入一个元素时,flag置为true。
3.每次从队列放出一个元素时,flag置为false。
4.当rear 等于 front&&flag 为 false 时,队列为空;当rear 等于 front&&flag 为 true 时,队列为满;当 rear 不等于 front&&flag 为 false 时,队列有元素但是没有满。

第三种方式:
1.队列中保留一个位置不放元素。
2.每次存放元素之前先行检查 rear 下一个值是不是front,队列为满。
3.当 front 等于rear 队列为空。

循环队列简单实现

public class MyCircularQueue<E> {
    private Object[] elem;
    private int front;
    private int rear;


    public MyCircularQueue(int k) {
        this.elem=new Object[k];
    }

    /**
     * 元素入队
     * @param value
     * @return
     */
    public boolean enQueue(E value) {
        if(isFull()){
            return false;
        }
        this.elem[rear]=value;
        if(rear==this.elem.length-1){
            rear=(rear+1)%this.elem.length;
        }else {
            rear++;
        }
        return true;
    }

    /**
     * 元素出队
     * @return
     */
    public boolean deQueue() {
        if(isEmpty()){
            return false;
        }
        this.elem[front]=null;
        if(front==this.elem.length-1){
            front=(front+1)%this.elem.length;
        }else {
            this.front++;
        }
        return true;
    }

    /**
     * 得到队头元素
     * @return
     */
    public E Front() {
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        return (E)this.elem[front];
    }
    /**
     * 得到队尾元素
     * @return
     */
    public E Rear() {
        if(isEmpty()){
            throw new RuntimeException("队列为空");
        }
        int index=-1;
        if(rear==0){
            index=this.elem.length-1;
        }else {
            index=rear-1;
        }
        return (E)this.elem[index];
    }

    /**
     * 判断队列是否为空
     * @return
     */
    public boolean isEmpty() {
        return rear==front;
    }
    /**
     * 判断队列是否为满
     * @return
     */
    public boolean isFull() {
        return (rear+1)%this.elem.length==front;
    }
}

优先级队列(保留)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值