队列的定义与实现

简介: 前面一章讲了栈的定义与实现,我们一样可以通过限制线性表的一些基本操作来实现另一种常用的数据结构---队列,这一章简单来讲讲队列的定义与实现。


一、定义



队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表,进行插入操作的一端称为队尾(rear),进行删除的一端为队头(front),插入数据元素的操作叫做入队,删除数据元素的操作叫做出队,它具有先进先出(First In First Out,FIFO)的特性。

微信图片15.png

二、队列的基本操作分析



前面章节说到,线性表可以通过顺序存储和链式存储来实现,作为操作受限的线性表也一样,所以后面也会通过两种存储结构来分析队列的基本操作实现。

在顺序存储结构中,一般会使用数组来实现,定义一个队列,约定使用 front 来存放队头元素的位置,使用 rear 来存放队尾的位置,当 front=rear=-1 时表示队列为空,入队和出队都是通过移动 rearfront 指针来实现,如下图所示,当 a9 入队后不能再做入队操作,而实际上空间并没有占满,此时会出现假溢出现象,为了避免这种情况,我们可以把该连续空间视为“循环顺序队列”。

微信图片17.png在循环顺序队列中,当 a9 入队后再做入队操作时,会将数据元素存储在数组前面出队后的空闲空间中,这样数据元素在数组中就会形成一个循环的队列,在这种情况下,当队满或者空队时都会存在 front=rear ,所以要通过 size 来判断队列是空还是满,当 size=array.length 时队满,当 size=0 时队空。使用循环队列时,队头和队尾的位置变换实现如下:


         

微信图片14.png在链式存储结构中,可以直接使用单向链表来实现队列,此时,我们把链表的头部作为队头,把链表的尾部作为队尾,也就是说,在链表尾部插入,链表头部删除,在代码实现中,需要定义两个指针 frontrear 分别指向链表的第1个结点和最后1个结点。

微信图片13.png

1. 入队


在顺序存储中进行入队操作,只需要通过 rear 来定位队尾位置,然后做入队操作,执行完后 rear 移到新的队尾位置。链式存储中,需要将新的结点添加到链表尾部,首先把 a4 赋值给 rear.next,然后新结点 a4 成为新的尾部结点。

微信图片12.png

2. 出队


顺序存储中进行出队操作,通过 front 定位并获取队头元素,然后做出队操作,执行完后 front 移动到新的队头位置。链式存储中,做出队操作时,获取到头部结点元素 a1 后,然后直接把 front.next 赋值给 front 来实现队头元素的删除。

微信图片11.png下面新建一个队列常规操作的接口,然后我们分别使用顺序结构(数组)和链式结构来实现它,读者可以分别对两种存储结构实现的接口的时间复杂度进行分析。

public interface Queue<T> {
    /**
     * 入队
     */
    boolean add(T t);
    /**
     * 出队
     */
    T remove();
    /**
     * 判断队列是否为空
     */
    boolean isEmpty();
    /**
     * 打印队列所有数据
     */
    void print();
}


三、队列的基本操作实现



和线性表实现一样,顺序结构使用数组来存储数据,链式结构使用结点来存储数据。


1. 顺序存储实现

public class ArrayQueue<T> implements Queue<T> {
    private int front = 0;
    private int rear = 0;
    private int size = 0;
    private Object[] elementData;
    public ArrayQueue(int size) {
        this.elementData = new Object[size];
    }
    @Override
    public boolean add(T t) {
        if (front == rear && size == elementData.length) {
            throw new ArrayIndexOutOfBoundsException();
        }
        elementData[rear] = t;
        rear = (rear + 1) % elementData.length;
        size++;
        return true;
    }
    @SuppressWarnings("unchecked")
    @Override
    public T remove() {
        if (front == rear && size == 0) {
            throw new NullPointerException();
        }
        Object t = elementData[front];
        elementData[front] = null;
        front = (front + 1) % elementData.length;
        size--;
        return (T) t;
    }
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
    @Override
    public void print() {
        System.out.println(Arrays.toString(elementData));
    }
}


2. 链式存储实现

public class LinkedQueue<T> implements Queue<T> {
    private Node front;
    private Node rear;
    private int size = 0;
    private class Node {
        private T t;
        private Node next;
        public Node() {
        }
        public Node(T t, Node next) {
            this.t = t;
            this.next = next;
        }
    }
    @Override
    public boolean add(T t) {
        Node n = new Node(t, null);
        if (rear != null) {
            rear.next = n;
        }
        if (front == null) {
            front = n;
        }
        rear = n;
        size++;
        return false;
    }
    @Override
    public T remove() {
        if (front == null) {
            throw new NullPointerException();
        }
        T t = front.t;
        front = front.next;
        size--;
        return t;
    }
    @Override
    public boolean isEmpty() {
        return size == 0;
    }
    @Override
    public void print() {
        Node n = front;
        while (n != null) {
            System.out.print(n.t + ",");
            n = n.next;
        }
        System.out.println();
    }
}


目录
相关文章
|
30天前
|
存储 算法 C语言
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)(下)
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)
32 2
|
22天前
|
存储 算法
数据结构和算法学习记录——特殊线性表之队列-队列的概念、队列结构体类型定义 、基本接口函数、初始化函数、销毁队列函数、入队列函数、判断队列是否为空、出队列函数、读取队头队尾的数据 、计算队列数据个数
数据结构和算法学习记录——特殊线性表之队列-队列的概念、队列结构体类型定义 、基本接口函数、初始化函数、销毁队列函数、入队列函数、判断队列是否为空、出队列函数、读取队头队尾的数据 、计算队列数据个数
16 0
|
30天前
|
算法 C语言 C++
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)(中)
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)
22 0
|
30天前
|
缓存 算法 C语言
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)(上)
从C语言到C++_19(容器适配器+stack和queue模拟实现+优先级队列priority_queue)
23 0
|
1月前
|
算法 编译器 C++
priority_queue简单实现(优先级队列)(c++)
priority_queue介绍 pri_que是一个容器适配器,它的底层是其他容器,并由这些容器再封装而来。类似于heap的结构。默认为大堆。
38 0
|
1月前
|
测试技术 C++
c++优先队列priority_queue(自定义比较函数)
c++优先队列priority_queue(自定义比较函数)
125 0
|
9月前
|
存储 Java
【数据结构】 队列(Queue)与队列的模拟实现
【数据结构】 队列(Queue)与队列的模拟实现
队列的定义、基本操作、顺序实现(初始化,入队,出队)
数据结构:队列的定义、基本操作、顺序实现(初始化,入队,出队)附有代码讲解
410 0
|
存储
队列的定义及基本操作实现(链式)
队列的定义及基本操作实现(链式)
100 0
|
存储
设计一个名为Queue的类用于存储整数。在栈中,元素以“后进先出”的方式获取。在队列中,元素以“先进先出”方法获取。
设计一个名为Queue的类用于存储整数。在栈中,元素以“后进先出”的方式获取。在队列中,元素以“先进先出”方法获取。
89 0