美团一面:循环队列听说过么,怎么实现?
这是一个或许对你有用的社群 一对一交流/面试小册/简历优化/求职解惑欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料《项目实战视频》从书中学往事上“练”《互联网高频面试题》面朝简历学习春暖花开《架构 x 系统设计》摧枯拉朽掌控面试高频场景题《精进 Java 学习指南》系统学习互联网主流技术栈《必读 Java 源码专栏》知其然知其所以然这是一个或许对你有用的开源项目国产Star破10w的开源项目前端包括管理后台、微信小程序后端支持单体、微服务架构RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能多模块https://gitee.com/zhijiantianya/ruoyi-vue-pro微服务https://gitee.com/zhijiantianya/yudao-cloud视频教程https://doc.iocoder.cn【国内首批】支持 JDK17/21SpringBoot3、JDK8/11Spring Boot2双版本来源飞天小牛肉顺序队列顺序队列定义假溢出问题循环队列顺序队列顺序队列定义队列的底层是数组我们常说的队列其实就是顺序队列其数据结构定义一般是队头指针指向数组第一个元素队尾指针指向数组最后一个元素的下一个位置为了避免当只有一个元素时队头和队尾重合使处理变得麻烦所以这里引入了队头和队尾两个指针假设front指针指向队头元素rear指针指向队尾元素的下一个位置这样当front rear时表示这个队列是空队列当front rear 1时表示这个队列中只有一个元素示意图如下众所周知队列是先进先出的那么进队操作对应的步骤就是先送值到队尾再将队尾指针 1// 送值到队尾 queue[rear] x; // 队尾指针 1 rear ;出队操作先取出队头元素再将队头指针 1// 取出队头元素 x queue[Q.front] // 队头指针 1 front ;假溢出问题顺序队列存在假溢出问题 就是明明在队列中仍然有可以存放元素的空间却无法执行入队操作了举个例子队列的大小是 5数组容量为 5一开始是空队列然后依次入队了 A、B、C、D然后 A 出队B 出队相应的 front 指针会往后移动两位再入队一个新元素 E此时 front 指针不变rear 指针需要 1已经超出了数组的下标范围就会导致新元素插入失败明明队列中还有空间插入元素竟然会失败这就是一种假性上溢出现象。如何解决这个问题呢有三种建立一个足够大的存储空间以避免溢出。这样做空间使用率低浪费存储空间移动元素每当出队一个元素就将移动队列中所有的已有元素向队头移动一个位置。这样做很明显时间复杂度比较高效率慢循环队列将队头和队尾看作是一个首尾相接的循环队列因此循环队列是解决顺序队列假溢出问题的最佳选择基于 Spring Boot MyBatis Plus Vue Element 实现的后台管理系统 用户小程序支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能项目地址https://github.com/YunaiV/ruoyi-vue-pro视频教程https://doc.iocoder.cn/video/循环队列循环队列的数据结构定义一般是队列长度固定即队列数组容量有限队列的头尾相接形成一个环当队尾到达数组的最后一个位置时下一个位置是数组的第一个位置具体实现步骤如下定义一个数组和两个指针front和rear分别表示队头和队尾的位置。初始时空队列队头和队尾都指向数组的第一个位置即front rear 0。入队时首先检查队列是否已满如何判断队列满牺牲一个单元来区分队空和队满即(rear 1) % maxsize front。如果满了则返回错误否则将元素添加到队尾即queue[rear] element然后将 rear 指针向后移动一位即rear (rear 1) % capacity。出队时首先检查队列是否为空**front rear就表示队列空** 。如果为空则返回错误否则将队头元素取出并返回即element queue[front]然后将front指针向后移动一位即front (front 1) % capacity。在队列的任何时刻队列中的元素数量为(rear - front capacity) % capacity示意图如下以下是一个基于数组实现循环队列的 Java 代码示例public class CircularQueue { // 存储元素的数组 privateint[] data; privateint front, rear; // 数组大小 privateint capacity; public CircularQueue(int k) { capacity k; data newint[capacity]; front 0; rear 0; } // 入队 public boolean enqueue(int element) { if (isFull()) { returnfalse; } else { data[rear] element; rear (rear 1) % capacity; returntrue; } } // 出队 public boolean dequeue() { if (isEmpty()) { returnfalse; } else { front (front 1) % capacity; returntrue; } } // 获取队头元素 public int front() { if (isEmpty()) { return -1; } else { return data[front]; } } // 获取队尾元素 public int rear() { if (isEmpty()) { return -1; } else { return data[(rear - 1 capacity) % capacity]; } } // 判断队列是否为空 public boolean isEmpty() { return front rear; } // 判断队列是否满 public boolean isFull() { return (rear 1) % capacity front; } }简单总结就是初始/队空front rear出队front (front 1) % capacity (最大元素个数)进队rear (rear 1) % capacity队列长度(rear - front capacity) % capacity队满牺牲一个单元来区分队空和队满 (rear 1) % capacity front欢迎加入我的知识星球全面提升技术能力。 加入方式“长按”或“扫描”下方二维码噢星球的内容包括项目实战、面试招聘、源码解析、学习路线。文章有帮助的话在看转发吧。 谢谢支持哟 (*^__^*