数据结构-队列

队列

一、队列概述

1.1 队列简介

1.1.1 队列定义
  • 队列就是一个先进先出的线性表
  • 它允许在表的一端插入数据,在另一端删除元素,插入元素的这一端称之为队尾
1.1.2 队列特性
  1. 在队尾插入元素,在队首删除元素。
  2. FIFO(先进先出)
1.1.3 结构
(1) 队头front:
  • 删除数据的一端。对于数组,从后面插入更容易,前面插入较困难,所以一般用数组实现的队列队头在前面。(删除直接index游标前进,不超过队尾即可)。而对于链表。插入删除在两头分别进行那么头部(前面)删除尾部插入是最方便的选择
(2) 队尾rear:
  • 插入数据的一端,同上,在数组和链表中通常均在尾部位置。
(3) 队长length:
对于顺序队列
  • length = rear - front
对于链式队列
  • length需提前创建一个变量来记录,以免靠遍历结点才能获取

1.2 队列分类

1.2.1 数组队列
(1)定义
  • 底层利用数组保存各个元素
(2)结构
  • 包含一个存储元素的数组
  • 整形变量 front 来标记队头位置
  • 整形变量 rear 标记队尾位置
1.2.2 链式队列
(1)存储结构
  • 底层为链表
  • 包含一个指向向队头结点的引用(指针)front,与一个指向向队尾结点的引用(指针)rear
  • 表示该队列的长度的整型变量 int length
1.2.3 双向队列
(1)特性
  • 在普通队列的基础上,两边均可进行插入删除操作
1.2.4 循环队列
(1)循环队列
  • 定义
    • 循环队列仍是数组实现的,但其中包含两个指针front,rear 指向队头,对尾,在添加队尾元素,与弹出对头元素时,改变front与rear的值,相互追赶,且对两个值进行求余,防止数组越界
(2) 采用循环队列原因
  1. 如果数组队列如果使用front指针来标识队头元素所在下标,每次出队时,都需要将front++,容易使得数组溢出,数组每一个位置只用一次,利用率极低,即每进行一次出队操作,数组可用空间就减一
  2. 如果不使用front,每次入队rear++,每次出队时,rear–,则需将后n-1个元素都前移一位,时间复杂度高
(3)操作算法
  1. 初始化:数组的front和rear都指向0.
  2. 入队:队不满,先队尾位置传值,再rear=(rear + 1) % maxsize;
  3. 出队:队不空,先取队头位置元素,front=(front + 1)%maxsize;
  4. 是否为空:return rear == front;
  5. 大小:return (rear+maxsize-front)%maxsize;
  6. 当rear = front时,队列可能为空,或者已经满,所以分两种情况
  • { (rear+1)%maxsize == front }==>队列为满
    在这里插入图片描述
  • { front == rear }==>队列为空

二、队列实现

2.1 队列操作接口

2.1.1 队列操作接口java实现
package com.niss.queue;

/**
 * @author Ni187
 */
public interface Queue<E> {

    /**
     * 清空队列
     * @return 清空队列结果
     */
    boolean clear();

    /**
     * 检查队列是否为空
     * @return 队列是否为空
     */
    boolean isEmpty();

    /**
     * 获取队列长度
     * @return 队列长度
     */
    int size();

    /**
     * 向队尾中添加元素
     * @param data 元素
     * @return 操作是否成功
     */
    boolean put(E data);

    /**
     * 删除对头元素
     */
    void remove();

    /**
     * 去除并删除队头元素
     * @return 队头元素
     */
    E poll();

    /**
     * 取出队头元素
     * @return 队头元素
     */
    E peek();

}

2.2 顺序队列

2.2.1 顺序循环队列java实现
package com.niss.queue;

import java.util.Arrays;

/**
 * @author Ni187
 */
public class SqQueue<E> implements Queue<E> {

    /**
     * 存储数组
     */
    private Object[] objects;

    /**
     * 队头下标位置
     */
    int front;

    /**
     * 队尾下标位置
     */
    int rear;

    private final static int INIT_SIZE = 100;

    public SqQueue(int size){
        if(size<=0){
            throw new RuntimeException("初始化大小异常!");
        }
        this.objects = new Object[size+1];
        this.front = this.rear = 0;
    }

    public SqQueue(){
        this(INIT_SIZE);
    }


    @Override
    public boolean clear(){
        try {
            Arrays.fill(this.objects, null);
            this.front = this.rear = 0;
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;

    }

    @Override
    public boolean isEmpty() {
        return front == rear;
    }

    @Override
    public int size() {
        return (rear+objects.length-front)%objects.length;
    }

    /**
     * 检查是否已满
     * @return 是否已满
     */
    public boolean isFull(){
        return (rear+1)%objects.length == front;
    }

    @Override
    public boolean put(E data) {
        if(isFull()){
            throw new RuntimeException("队列已满!");
        }
        objects[rear] = data;
        rear = (rear+1)%objects.length;
        return true;
    }

    @Override
    public void remove() {
        objects[front] = null;
        front = (front+1)%objects.length;
    }

    @Override
    public E poll() {
        Object object = peek();
        remove();
        return (E)object;
    }

    @Override
    public E peek() {
        if(isEmpty()){
            throw new RuntimeException("空队列!");
        }
        return (E)objects[front];
    }

}

2.3 链式队列

2.3.1 链式队列java实现
package com.niss.queue;

/**
 * @author Ni187
 */
public class LinkedQueue<E> implements Queue<E> {

    private static class Node<E>{
        E elem;
        Node<E> next;
        public Node(E elem,Node<E> next){
            this.elem = elem;
            this.next = next;
        }
    }

    /**
     * 队头结点
     */
    private Node<E> front;

    /**
     * 对尾节点
     */
    private Node<E> rear;

    /**
     * 队列长度
     */
    int length;

    public LinkedQueue(){
        this.rear = this.front = new Node<E>(null,null);
        this.length = 0;
    }

    private void checkSize(){
        if(this.length <= 0){
            throw new RuntimeException("空队列!");
        }
    }

    @Override
    public boolean clear(){
        this.rear = this.front = new Node<E>(null,null);
        this.length = 0;
        return true;
    }

    @Override
    public boolean isEmpty() {
        return this.length == 0;
    }

    @Override
    public int size() {
        return this.length;
    }

    @Override
    public boolean put(E data) {
        this.rear.next = new Node<E>(data,null);
        this.rear = rear.next;
        ++this.length;
        return true;
    }

    @Override
    public void remove() {
        checkSize();
        this.front = this.front.next;
        this.front.elem = null;
        --this.length;
    }

    @Override
    public E poll() {
        E elem = this.peek();
        this.remove();
        return elem;
    }

    @Override
    public E peek() {
        checkSize();
        return this.front.next.elem;
    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值