数据结构之队列

简介: 数据结构之队列

队列特征


网络异常,图片无法展示
|


队列的实现


网络异常,图片无法展示
|


依旧是基于我们自己封装的Array。


public class Queue<E> implements QueueInterface<E> {
    private Array<E> array;
    public Queue(int capacity) {
        array = new Array<>(capacity);
    }
    public Queue() {
        this(10);
    }
    @Override
    public void enqueue(E e) {
//        加入元素
        array.addLast(e);
    }
    @Override
    public E dequeue() {
//        取出第一个元素
        return array.removeFirst();
    }
    @Override
    public E getFront() {
        return array.getFirst();
    }
    @Override
    public int getSize() {
        return array.getSize();
    }
    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }
    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append("Queue [");
        for(int i = 0; i < array.getSize(); i++) {
            res.append(array.get(i));
            if(i != array.getSize() - 1) {
                res.append(",");
            }
        }
        res.append("]");
        return  res.toString();
    }
}


复杂度分析


网络异常,图片无法展示
|


由于上面出队的时间复杂度为o(n),结合队列的特征,我们可以使用循环队列来解决这个问题。


由于,我们出队时,后面的元素顺序是不会改变的。所以我们没必要把后面的元素依次向前移动。


网络异常,图片无法展示
|


网络异常,图片无法展示
|


网络异常,图片无法展示
|


网络异常,图片无法展示
|


循环队列


基于上面的分析,我们可以编写出一下结构。


  • 入队的时候,有益让数组空出一个位置,为了判断队列已满。(tail + 1)% arr.length == front。


  • 扩容的时候,巧妙地使用了size。让i来控制front向下移动。让其按照顺序加入新队列。


  • front始终指向队首元素,tail始终指向队尾的下一个位置。


  • 所有循环的获取位置都是通过 % arr.length


public class LoopQueue<E> implements QueueInterface<E> {
    private E[] arr;
    private int front;
    private int tail;
    private int size;
    public LoopQueue(int capacity) {
//        为了满足tail + 1 == front为满
        arr = (E[]) new Object[capacity + 1];
        front = 0;
        tail = 0;
        size = 0;
    }
    public LoopQueue() {
        this(10);
    }
    @Override
    public void enqueue(E e) {
//        入队
        if((tail + 1) % arr.length == front) {
//            未删除,并且队列已满
//            throw new Error("(tail + 1) % arr.length == front, 队列已满");
            resize(getCapacity() * 2);
        }
        arr[tail] = e;
        tail = (tail + 1) % arr.length;
        size++;
    }
    public void resize(int capacity) {
        E[] newArr = (E[]) new Object[capacity + 1];
        // 巧妙地使用了size。让i来控制front向下移动。
        for(int i = 0; i < size; i++) {
//            这里就将队列中的元素按顺序加入了
            newArr[i] = arr[(i + front) % arr.length];
        }
        arr = newArr;
        front = 0;
        tail = size;
    }
    @Override
    public E dequeue() {
        if(isEmpty()) {
            throw new Error("Queue is empty");
        }
        E e = arr[front];
        arr[front] = null;
//        移动头指针。
        front = (front + 1) % arr.length;
        size--;
        if(size == getCapacity() / 4 && getCapacity() / 2 != 0)  {
            resize(getCapacity() / 2);
        }
        return e;
    }
    @Override
    public E getFront() {
        if(isEmpty()) {
            throw new Error("Queue is empty");
        }
        return arr[front];
    }
    public int getCapacity() {
        return arr.length - 1;
    }
    @Override
    public int getSize() {
        return size;
    }
    @Override
    public boolean isEmpty() {
        return false;
    }
    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("LoopQueue capacity %d, size %d", getCapacity(), size));
        res.append(" front [");
        for(int i = front; i != tail ; i = (i + 1) % arr.length) {
            res.append(arr[i]);
            if((i + 1) % arr.length != tail) {
                res.append(",");
            }
        }
        res.append("] tail");
        return  res.toString();
    }
}


循环队列复杂度分析


网络异常,图片无法展示
|


队列和循环队列的复杂度比较


网络异常,图片无法展示
|

相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
264 9
|
4天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
114 75
|
3月前
|
缓存 算法 调度
数据结构之 - 双端队列数据结构详解: 从基础到实现
数据结构之 - 双端队列数据结构详解: 从基础到实现
125 5
|
4天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
25 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
4天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
28 9
|
4天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
23 7
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
79 5
|
2月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
3月前
初步认识栈和队列
初步认识栈和队列
68 10
|
3月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
36 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列