salesforce零基础学习(七十七)队列的实现以及应用
队列和栈简单的区别为栈是后进先出,队列是先进先出。队列也是特殊的线性表,所以队列也分为顺序存储结构和链式存储结构。本篇主要描述顺序存储结构。
我们先假定一个队列里有5个元素,当我们添加新元素时,添加到队列的最后一个位置,所以时间复杂度为O(1),当我们弹出元素时,需要将队列头部的元素弹出,并将后面的元素整体向前面平移,所以时间复杂度为O(n)。如果频繁的弹出,并且后面的元素向前面平移,这样对于性能还是影响挺大的,所以我们可以增加头指针,尾指针,不要求第一个元素必须在index为0的位置,只需要用头指针记录当前的头在哪里就好。
一.环形队列:
使用两个指针操作步骤为:
1.当在队尾添加元素情况下,队尾的指针+1,如下图,队列中添加a1,a2,a3,a4四个元素。此时队首front指针指向0,队尾rear指针指向4;
2.将队首元素进行弹出,此时队首指针front指向1,队尾指向4;
3.将元素a5添加到队尾,此时队尾指针指向到了内存长度的外面,但是下标为0还是有空缺的地方,这种情况称为假溢出。
为了避免假溢出这种情况,我们的做法为当队列满了以后,从头开始继续存储队列,直到队列满,即上图的情况下,a5进入队列以后,队尾rear指针指向下标0.
此时针对队列的空或者满的判断,可以通过队首指针和队尾指针来判断:
1.判断队列为空的条件为:front = rear,即首指针等于尾指针;
2.因为队尾可以从头开始,所以rear可以大于front,也有可能rear小于front。当队列满时,我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。这样我们可以通过下面的表达式来判断队列已满:(rear+1) % QueueSize = front.上图中当添加完a5以后,队列中只剩下一个空闲单元我们就假定此队列已满。
3.获取当前队列的元素个数:(rear - front + QueueSize)% QueueSize
二.代码实现
代码中封装了实现队列的基本方法,判断队列是否为空,是否是满的队列,添加元素,弹出元素等。其中针对添加元素,需要考虑队列是否已经满的情况,对于弹出元素,需要考虑队列是否为空队列的情况。
- public with sharing class Queue {
- //数据集
- private Object[] datas{get;set;}
- //栈最大容量
- private Integer maxSize{get;set;}
- //队头的位置指针
- private Integer front{get;set;}
- //队尾的位置指针
- private Integer rear{get;set;}
- public Queue() {
- this(10);
- }
- public Queue(Integer queueSize) {
- datas = new Object[queueSize];
- maxSize = queueSize;
- front = 0;
- rear = 0;
- }
- //添加元素到队列尾部,如果添加成功返回true,添加失败返回false
- public Boolean add(Object obj) {
- if(datas == null) {
- throw new QueueException('队列未初始化');
- }
- if(full()) {
- throw new QueueException('队列已满');
- }
- datas[rear] = obj;
- rear = Math.mod(rear + 1, maxSize);
- //队列
- return true;
- }
- //返回队列头的元素,不弹出头元素
- public Object peek() {
- if(datas == null) {
- throw new QueueException('队列未初始化');
- }
- return datas[front];
- }
- //弹出头元素
- public Object poll() {
- if(datas == null) {
- throw new QueueException('队列未初始化');
- }
- if(empty()) {
- throw new QueueException('队列为空!');
- }
- Object returnObj = datas[front];
- datas[front] = null;
- front = Math.mod((front + 1),maxSize);
- return returnObj;
- }
- public Boolean empty() {
- return front == rear;
- }
- public Boolean full() {
- return front == Math.mod(rear + 1, maxSize);
- }
- public Integer size() {
- return Math.mod(rear - front + maxSize ,maxSize);
- }
- override public String toString() {
- List<Object> objList = new List<Object>();
- Integer tempRear;
- if(rear < front) {
- tempRear = rear + maxSize;
- } else {
- tempRear = rear;
- }
- for(Integer i = front;i<=tempRear;i++) {
- if(datas[Math.mod(i, maxSize)] != null) {
- objList.add(datas[Math.mod(i, maxSize)]);
- }
- }
- return String.join(objList, ',');
- }
- public class QueueException extends Exception{
- }
- }
三.测试举例:
1.队列超出内存情况:初始化一个长度为5的队列,因为队列满的时候,会空出一个元素空间,所以说实际可以添加进队列的长度为4,当添加eee的时候会报错,因为队列已满。
- Queue q = new Queue(5);
- q.add('aaa');
- q.add('bbb');
- q.add('ccc');
- q.add('ddd');
- q.add('eee');
- System.debug(LoggingLevel.INFO, '*** q: ' + q);
2.正常使用添加弹出效果,每次弹出是弹出队首指针对应的元素
- Queue q = new Queue(5);
- q.add('aaa');
- q.add('bbb');
- q.add('ccc');
- q.add('ddd');
- String result = (String)q.poll();
- System.debug(LoggingLevel.INFO, '*** result: ' + result);
- System.debug(LoggingLevel.INFO, '*** : ' + 'aaa'.equals(result));
- q.add('eee');
- System.debug(LoggingLevel.INFO, '*** q: ' + q);
总结:环形队列适用于已经知道需要分配多大内存的情况,如果不知道需要分配多少内存的情况,可以使用队列的链形结构。队列在程序中经常使用,比如场景为排队等的场景,如果有此种先进先出的场景,优先选择队列来实现。此篇只是简单的构造一下队列的模型,很多地方需要完善,有需要或者感兴趣的自行完善一下。篇中有错误的地方欢迎指出,有问题欢迎留言。
salesforce零基础学习(七十七)队列的实现以及应用的更多相关文章
- 【转】【Salesforce】salesforce 零基础学习(十七)Trigger用法
看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...
- salesforce 零基础学习(十七)Trigger用法
看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...
- salesforce 零基础学习(五十二)Trigger使用篇(二)
第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...
- salesforce零基础学习(八十七)Apex 中Picklist类型通过Control 字段值获取Dependent List 值
注:本篇解决方案内容实现转自:http://mysalesforceescapade.blogspot.com/2015/03/getting-dependent-picklist-values-fr ...
- salesforce零基础学习(八十二)审批邮件获取最终审批人和审批意见
项目中,审批操作无处不在.配置审批流时,我们有时候会用到queue,related user设置当前步骤的审批人,审批人可以一个或者多个.当审批人有多个时,邮件中获取当前记录的审批人和审批意见就不能随 ...
- salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现
项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...
- salesforce 零基础学习(六十八)http callout test class写法
此篇可以参考: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restfu ...
- salesforce零基础学习(八十九)使用 input type=file 以及RemoteAction方式上传附件
在classic环境中,salesforce提供了<apex:inputFile>标签用来实现附件的上传以及内容获取.salesforce 零基础学习(二十四)解析csv格式内容中有类似的 ...
- salesforce零基础学习(九十六)Platform Event浅谈
本篇参考:https://developer.salesforce.com/blogs/2018/07/which-streaming-event-do-i-use.html https://trai ...
- salesforce零基础学习(一百零五)Change Data Capture
本篇参考: https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/using ...
随机推荐
- 关于MATLAB处理大数据坐标文件2017526
运行六个特征,提高了3分,也就是说以前做的特征已经用完了,穷途末路,依靠以前的特征已经很难取得进步了,提出以下建议 1.测试集曾经运行错误的数据尽早画出图形,并尽可能发现问题并提出特征 2.运行其他程 ...
- 神奇的 conic-gradient 圆锥渐变
感谢 LeaVerou 大神,让我们可以提前使用上这么美妙的属性. conic-gradient 是个什么?说到 conic-gradient ,就不得不提的它的另外两个兄弟: linear-grad ...
- Kafka 客户端实现逻辑分析
这里主要分析kafka 客户端实现 (代码分析以perl kafka实现为准) kafka客户端分为生产者和消费者,生产者发送消息,消费者获取消息. 在kafka协议里客户端通信中用到的最多的四个协议 ...
- Example006为弹出窗口加入关闭按钮
<!-- 实例006为弹出的窗口加入关闭按钮 --> <head> <meta charset="UTF-8"> </head> & ...
- PouchDB 基础
GUIDES http://pouchdb.com/guides/ 1.建立couchDB环境 下载并安装CouchDB: https://couchdb.apache.org/#download 测 ...
- tomcat+jdk+mysql
转自 http://www.cnblogs.com/liulinghua90/ ,写的很详细,转来共享私藏 按照下面的步骤一步一步来搭建tomcat+jdk+mysql环境. [Linux环境]- ...
- 网络编程学习笔记(二)基于TCP的Socket编程
1.Socket:英文意思插座.两个Java应用程序可以通过一个双向的网络通信连接实现数据交换,这个双向链路的一端称为一个Socket. 2.Socket通常用来实现client-server(客户端 ...
- PostgreSQL 使用 PreparedStatement 导致查询慢的分析
实验环境: DB is PostgreSQL version 8.2.15 JDK1.8 测试一 使用JDBC查询一个SQL: public static void test1(String url, ...
- vue子父组件通信
之前在用vue写子父组件通信的时候,老是遇到问题!!! 子组件传值给父组件: 子组件:通过emit方法给父组件传值,这里的upparent是父组件要定义的方法 模板: <div v-on:cli ...
- javaScript事件绑定
事件绑定,就是要对某一个东西进行操作.(因为你想让他实现什么效果,所以就得绑定他,哈哈哈!) 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函 ...