当前位置: 首页 > news >正文

[数据结构] 队列 (Queue)

1.概念

队列 : 只允许在一段进行插入数据操操作 , 在另一端进行删除数据操作的特殊线性表 ; 队列先进先出

入队列 : 进行插入操作的一端称为队尾

出队列 : 进行删除操作的一端称为对头

2.队列的使用

在Java中 , Queue 是一个接口 , 底层通过链表实现的

方法

行为

说明

add(E e)

添加元素到队尾(若队列已满,抛出 IllegalStateException

推荐使用 offer()

offer(E e)

添加元素到队尾(队列满时返回 false

更安全的插入方式

remove()

移除并返回队头元素(队列空时抛出NoSuchElementException

推荐使用 poll()

poll()

移除并返回队头元素(队列空时返回 null

安全的移除方式

element()

查看队头元素(不删除,队列空时抛出异常)

推荐使用 peek()

peek()

查看队头元素(不删除,队列空时返回 null

安全的查看方式

public static void main(String[] args) {Queue<Integer> queue = new LinkedList<>();queue.offer(11);//添加元素到队尾queue.offer(12);queue.offer(13);queue.offer(14);queue.offer(15);System.out.println(queue);//打印队列  [11, 12, 13, 14, 15]int a1 = queue.poll();//移除头元素,并返回System.out.println(a1);//11System.out.println(queue);//[12, 13, 14, 15]int a2 = queue.peek();//获取队头元素System.out.println(a2);//12
}

3.队列的模拟实现

①实现队列

public class MyQueue {public static class ListNode{public int val;public ListNode prev;public ListNode next;public ListNode(int val){this.val = val;}}public int usedSize = 0;public ListNode head = null;public ListNode last = null;public boolean isEmpty(){//检查是否为空return usedSize == 0;//如果是空的 , usedSize为0 返回true}public void offer(int val){//入队列,采用的是尾插法ListNode node = new ListNode(val);if(isEmpty()){head = last =  node;//把node节点赋值给head和lastusedSize++;}else {last.next = node;node.prev = last;last = node;usedSize++;}}public int poll(){//相应的出队列应该采用,头删法if(isEmpty()) {return -1;}int vall = head.val;head = head.next;if(head != null){head.prev = null;}usedSize--;return vall;}public int size(){//返回大小return usedSize;}}

②测试

public static void main(String[] args) {MyQueue myQueue = new MyQueue();myQueue.offer(11);//添加元素到队尾myQueue.offer(12);myQueue.offer(13);myQueue.offer(14);myQueue.offer(15);System.out.println(myQueue.poll());
}

4.循环队列

  • 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”
  • 循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间
  • 但是使用循环队列,我们能使用这些空间去存储新的值

方法名

描述

参数

返回值

特殊说明

MyCircularQueue(k)

构造器,初始化队列,设置队列容量为 k

int k(队列容量)

内部实际使用 k+1 的空间来区分空满状态

Front()

获取队首元素

int(队首元素值)

队列为空时返回 - 1

Rear()

获取队尾元素

int(队尾元素值)

队列为空时返回 - 1

enQueue(value)

向队列插入元素

int value(待插入元素)

boolean(插入成功返回 true,队列满则返回 false)

插入后队尾指针循环后移

deQueue()

从队列删除队首元素

boolean(删除成功返回 true,队列为空则返回 false)

删除后队首指针循环后移

isEmpty()

检查队列是否为空

boolean(为空返回 true,否则返回 false)

当 front == rear 时队列空

isFull()

检查队列是否已满

boolean(已满返回 true,否则返回 false)

当 (rear+1) % 容量 == front 时队列满

class MyCircularQueue {public int front;public int rear;public int[] elem;public MyCircularQueue(int k) {elem = new int[k+1];}//入队列 public boolean enQueue(int value) {if(isFull()) {return false;}elem[rear] = value;rear = (rear+1)%elem.length;return true;}//出队列 public boolean deQueue() {if(isEmpty()) {return false;}front = (front+1)%elem.length;return true;}//得到队头元素 public int Front() {if(isEmpty()) {return -1;}return elem[front];}public int Rear() {if(isEmpty()) {return -1;}int index = (rear == 0) ? elem.length-1 : rear-1;return elem[index];}public boolean isEmpty() {return rear == front;}public boolean isFull() {return (rear+1)%elem.length == front;}}

5.双端队列(Deque)

双端队列 是 指允许两端都可以进行入队和出队操作的队列

Deque是一个接口, 使用时 必须创建LinkedList对象

Deque的接口比较多 , 栈和队列均可以实现该接口

public static void main(String[] args) {Deque<Integer> stack = new LinkedList<>();//双端队列的链式实现Deque<Integer> queue = new ArrayDeque<>();//双端队列的线性实现
}

6.用队列实现栈

  1. 模拟的入栈操作 : 将元素放到不为空的队列中
  2. 模拟的出栈操作 : 把不为空的队列中的size-1个元素放到另一个队列中 ; 最后剩下的就是模拟栈中的顶层元素
import java.util.LinkedList;
import java.util.Queue;class MyStackUseQueue {public Queue<Integer> qu1;public Queue<Integer> qu2;public MyStackUseQueue() {qu1 = new LinkedList<>();qu2 = new LinkedList<>();}public void push(int x) {if(!qu1.isEmpty()) {qu1.offer(x);}else if(!qu2.isEmpty()) {qu2.offer(x);}else {qu1.offer(x);}}public int pop() {if(empty()) {return -1;}if(!qu1.isEmpty()) {int size = qu1.size();for(int i = 0;i < size-1;i++) {qu2.offer( qu1.poll());}return qu1.poll();}else  {int size = qu2.size();for(int i = 0;i < size-1;i++) {qu1.offer( qu2.poll());}return qu2.poll();}}public int top() {if(empty()) {return -1;}if(!qu1.isEmpty()) {int size = qu1.size();int val = 0;for(int i = 0;i < size;i++) {val = qu1.poll();qu2.offer(val);}return val;}else  {int size = qu2.size();int val = 0;for(int i = 0;i < size;i++) {val = qu2.poll();qu1.offer(val);}return val;}}public boolean empty() {return qu1.isEmpty() && qu2.isEmpty();}
}

7.用栈实现队列

  1. 模拟入队操作 : 放到第一个栈中
  2. 模拟出队操作 : 判断第二个栈是否为空 ?

如果为空 : 需要把第一个栈中的所有元素都放到第二个栈里 , 取出第二个栈中的顶层元素

如果不为空 : 直接取出第二个栈中的顶层元素

import java.util.ArrayDeque;class MyQueueUseStack {public ArrayDeque<Integer> stack1;public ArrayDeque<Integer> stack2;public MyQueueUseStack() {stack1 = new  ArrayDeque<>();stack2 = new  ArrayDeque<>();}public void push(int x) {stack1.push(x);}public int pop() {if(empty()) {return -1;}if(stack2.isEmpty()) {//第一个栈里面所有的元素 放到第二个栈当中 while(!stack1.isEmpty()) {stack2.push(stack1.pop());}}return stack2.pop();}public int peek() {if(empty()) {return -1;}if(stack2.isEmpty()) {//第一个栈里面所有的元素 放到第二个栈当中 while(!stack1.isEmpty()) {stack2.push(stack1.pop());}}return stack2.peek();}public boolean empty() {return stack1.isEmpty() && stack2.isEmpty();}
}


文章转载自:

http://2zkQZmh7.mktms.cn
http://ryjjtfnO.mktms.cn
http://9vLVH2p3.mktms.cn
http://gpnvVi1W.mktms.cn
http://mBTUH4Ay.mktms.cn
http://tWryrlpa.mktms.cn
http://gcp3v1Cm.mktms.cn
http://BQuumoEA.mktms.cn
http://3nMxqbr2.mktms.cn
http://rUu3aCL2.mktms.cn
http://Kpwe4TIk.mktms.cn
http://jokadug1.mktms.cn
http://NrrUNy1Y.mktms.cn
http://nJTwJb8Z.mktms.cn
http://a0TyfrJu.mktms.cn
http://8NXuepav.mktms.cn
http://ekIuUhp6.mktms.cn
http://oQlrt4Qu.mktms.cn
http://tJxz0fca.mktms.cn
http://RBnfpwVk.mktms.cn
http://kdNE2KTI.mktms.cn
http://AB6dNdz6.mktms.cn
http://9lVMQdLG.mktms.cn
http://TYvbf85G.mktms.cn
http://MDTh91oh.mktms.cn
http://xfIw3gkA.mktms.cn
http://hiSku2Ac.mktms.cn
http://6h1KsKOq.mktms.cn
http://X3KNCt95.mktms.cn
http://4PDnpRIW.mktms.cn
http://www.dtcms.com/a/382015.html

相关文章:

  • Git : 基本操作
  • Vue模板中传递对象或数组时,避免直接使用字面量[]和{}
  • 26考研——内存管理_虚拟内存管理(3)
  • FastAPI如何用契约测试确保API的「菜单」与「菜品」一致?
  • PDFgear:免费全能的PDF处理工具
  • 贪心算法应用:K-Means++初始化详解
  • Linux相关概念和易错知识点(43)(数据链路层、ARP、以太网、交换机)
  • 交换机数据管理
  • 【Redis#11】Redis 在 C++ 客户端下的安装使用流程(一条龙服务)
  • leetcode 315 计算右侧小于当前元素的个数
  • MYSQL端口号3306被占用
  • Python核心技术开发指南(062)——静态方法
  • [Windows] 整容脸比对系统
  • C语言:指针从入门到精通(上)
  • 【MySQL】--- 表的约束
  • SpringBoot 轻量级一站式日志可视化与JVM监控
  • Java零基础学习Day10——面向对象高级
  • JavaScript中ES模块语法详解与示例
  • 系统核心解析:深入操作系统内部机制——进程管理与控制指南(三)【进程优先级/切换/调度】
  • Roo Code:用自然语言编程的VS Code扩展
  • 第8.4节:awk的内置时间处理函数
  • leetcode算法刷题的第三十四天
  • 【技术博客分享】LLM推理过程中的不确定问题
  • Vue3基础知识-setup()、ref()和reactive()
  • 规则系统架构风格
  • 宋红康 JVM 笔记 Day17|垃圾回收器
  • vue表单弹窗最大化无法渲染复杂组件内容
  • 加餐加餐!烧烤斗破苍穹
  • SCSS 中的Mixins 和 Includes,%是什么意思
  • RFID基础了解 --- RC522