【动漫宅也要写代码 基础篇】某队列的超电磁炮
来源:互联网 发布:linux定时脚本怎么编辑 编辑:程序博客网 时间:2024/06/11 19:34
【队列】一种FIFO(先进先出)的线性表结构
萌新的个人整合,请各位大神勿喷(萌新抱腿)
【动漫世界观】
以下动漫背景请参照《某科学的超电磁炮(とある科学の超電磁砲)》
不要告诉我你作为动漫宅连炮姐都不知道(傲娇脸)
【问题背景】
学园都市一年一度(?)的超能力测试(体检)来了,为了防止发生混乱,超能力者们要在检测处排队进行超能力等级检测。
每次排在队伍最前面的人会被叫去检测,而新来的人只能排在队伍的最后。在排队过程中,不允许插队、交换位置。
现在,御坂美琴(炮姐)、上条当麻(当妈)、白井黑子(百合黑子)、御坂妹(不知道是第几号)、一方通行(萝莉控)要来排队进行检测(不要问我为什么御坂妹和一方萝莉控也要来检测),请你模拟这一过程。
【普通队列】
这不就是排队吗?要用什么数据结构呢?
顾名思义,排队排队,就是要用队列嘛。
队列,是一种线性表结构。它的主体是一个数组,第一个队内元素所在的位置叫做队首,而最后一个元素所在的位置叫做队尾。队列允许在队首队尾进行操作。
此外,队列还具有一个特殊而重要的性质FIFO(先进先出)。
什么?你说你没听懂?那么下面我们就来实际模拟一下:
- 1.【建队与初始化】 首先我们需要一个建立一个队列
#define MaxSize 10010int Queue[MaxSize], Head, Tail;
其中
回到问题背景。一开始,队内是没有人的,那么队头指针与队尾指针都指向0号元素(就是没有)
Head = Tail = 0;
这样就初始化好了。如下图所示:
(Head、Tail指针指向检测处(0号))
- 2.【入队】接下来有人要入队了!
(Head指针指向检测站(0号)、Tail指针指向炮姐(1号))
那么这怎么在代码中实现呢?
void InQueue(int x) { Queue[++Tail] = x; return ;}
这就是入队函数,
484很简单?
- 3.【出队】又有几个人进来了,现在排在第一的炮姐要被叫去检测了
(Head指针指向检测站(0号)、Tail指针指向一方(4号))
(Haed指针指向空(1号)、Tail指针指向一方(4号))
代码实现依旧简单:
int OutQueue() { return Queue[Head++];}
这就是出队函数,就是把
- 4.【判断队伍是否为空】那么现在在进行了几轮操作(出队与入队)后,检测处的工作人员想知道这时还有没有人在排队等候,请你帮助他们。
(Head指针指向空2(2号)、Tail指针指向御坂妹(5号),队列非空)
(Head指针指向空5(5号)、Tail指针指向空5(5号),队列为空)
其实只要判断
bool Empty() { return Head == Tail;}
5.【小结】现在知道什么是FIFO(先进先出)了吗?
因为在操作过程中,任何先入队的元素一定会先出队(因为不能插队),比如当妈就绝对不能比先来的炮姐早走(就算是CP也不能插队),所以这保证了入队与出队的有序性。
【循环队列】
你以为这样事情就结束了?图样图森破,上台拿衣服。
为了模拟排队,你开了一个如下的队列:
int Queue[20001], Head, Tail;
这时来了20000个御坂妹(别问我为什么会有20000个御坂妹,就当实验还没开始吧),她们不断进行着如下操作:
1号御坂入队,然后出队;
2号御坂入队,然后出队;
3号御坂入队,然后出队;
。。。
20000号御坂妹入队,然后出队。
(Head指针指向空20000(20000号)、Tail指针指向空20000(20000号))
这时,我们可爱的20001号御坂“最后之作”来了,她也想来玩玩。
可是正当她想入队的时候,竟然
明明队里一个人都没有,怎么不能进入?御坂御坂不解地问道。
原来,每次操作后,
现在令你限时解决这个问题,不然一方萝莉控将会对你进行严肃的制裁。
其实这种因Head与Tail指针到达数组上界而无法入队的情况叫做假溢出。这时候要用循环队列解决。
什么是循环队列呢?就是在
#define MaxSize 20001int Queue[MaxSize], Head, Tail, Size;void InQueue(int x) { Tail = (Tail + 1) % MaxSize, ++Size; Queue[Tail] = x; return ;}int OutQueue() { int Ret = Queue[Head]; Head = (Head + 1) % MaxSize, --Size; return Ret;}bool Empty() { return !Size;}
我们发现,在原有的变量的基础上,多了一个
在入队与出队时,将原来的
这样问题就解决了。皆大欢喜!
【小结】循环队列是普通队列的一种改进,用于节省储存空间,建议在不知道操作次数多少时尽量使用循环队列。
【单调队列】
虽然排队的问题圆满解决绝了,但我们的任务还未结束。
- 【问题】超能力等级测试后,炮姐和她的小伙伴们站成了一排,请问你能求出每段长度为k的区间内等级最高的是谁吗?
已知:
上条当麻——Lev.0 把妹之手 幻想杀手;
一方通行——Lev.5 矢量操纵;
御坂妹妹——Lev.2 缺陷电力;
御坂美琴——Lev.5 超电磁炮;
白井黑子——Lev.4 瞬间移动。
- 【题解】
这是一道经典的单调队列题目
顾名思义,单调队列可以保证队内元素时刻保持单调(单调递增、单调递减、单调非减、单调非增)。
单调队列虽然叫“队列”,但其实和队列有很大差别:为了保证队内元素单调,会强行舍弃队中的一些元素。这点与FIFO的队列有很大不同,所以应该把单调队列看作是原数列的一个单调子序列。
1.【建队与初始化】单调队列的建队与初始化与队列相同,但建议使用循环队列。在此不赘述。
2.【入队】单调队列的入队是与普通队列区别最大的一项,下以单调非增队列为例:
void InQueue(int x) { int To = (Tail + 1) % MaxSize, ++Len; while(Queue[Tail] < x && Len) { To = (To - 1) % MaxSize; --Len; } Queue[To] = x; return ;}
入队时,将新入队的元素与队内的元素从后往前一一比较,直到找到第一个不比它小的元素,然后将新入队的元素插入该元素后,并将该元素后的所有原有元素舍弃。
回到原题,我们举k=2的情况。现在将1号当妈入队,因为队内为空,所以,将Tail指针指向当妈:
(Head = 0,Tail = 1)
因为还没有到第1个长度为2的区间[1,2],所以接着讲一方入队。这时我们的当妈就被(欢乐地)挤了出去:
(Head = 0, Tail = 1)
这时,到了第一个长度为2的区间[1,2],所以弹出队首(队列中最大的一项),就是该区间内最大的一项。所以区间[1,2]的答案为Lev.5。
3.【出队】出队比较简单,判断队首是否在需要操作的区间内,是就留下,不是就舍弃:
int OutQueue() { if(Queue[Head]在区间内) reutrn 0; int Ret = Queue[Head]; Head = (Head + 1) % MaxSize, --Len; return Ret; }
再回到原题,现在要从[1,2]区间变成[2,3]区间,所以要将1号出队,3号入队。
但是我们发现队首是2号一方,2号在[2,3]区间内,所以不用出队。
(Head = 0, Tail = 1)
将3号御坂妹入队,显然挤不走一方:
(Head = 0, Tail = 2)
所以[2,3]区间内的答案还是队首一方,Lev.5。
接着将[2,3]变为[3,4],2号出队,4号入队。
我们发现队首是2号一方,不在[3,4]区间内,出队:
(Head = 1, Tail = 2)
然后4号炮姐入队,将3号御坂妹挤走:
(Head = 1, Tail = 2)
所以[3,4]区间内的答案就是队首炮姐,Lev.5。
剩下以此类推。
4.【小结】
单调队列虽然没有普通队列的应用广泛,使用起来也容易与堆重复,但还是属于常见的数据结构。
而且单调队列虽然思想简单,操作起来还是有一定的难度的。(我就被卡了好久)
所以建议大家不妨多写几道题练练手:(以下题目来自洛谷)
http://www.luogu.org/problem/lists?name=&orderitem=pid&tag=56
【PS】 C++的STL里有一个叫“优先队列”的模板,虽然叫队列但实际功能更像是另外一个数据结构——堆,所以在此我就不讲了,放到以后堆的内容里。(虽然单调队列还算是优先队列的一种)
想了解的朋友可以自行百度。就连队列也有STL的模板哟。
OK,今天就讲到这里。撒哟那拉,米娜桑。
- 【动漫宅也要写代码 基础篇】某队列的超电磁炮
- 某科学的间断超电磁炮
- 超科学的电磁炮
- 问题C:某计算器的超电磁炮
- 问题 C: 某计算器的超电磁炮(加减乘除括号表达式求值)
- 电磁炮基础控制板
- 电磁兼容的重要性
- 电磁屏的原理
- 从一道物理题来看电磁炮的工作原理
- 动漫迷看的一点动漫
- 好看的日本动漫
- 看过的动漫
- 好看的动漫 壁纸
- 好看的动漫集合
- 我的动漫
- 电磁干扰滤波器的设计
- 电磁兼容问题的抑制方法
- 电磁干扰的耦合途径
- 部分博文将搬至新浪
- 文本情感分类(二):深度学习模型
- 记事本的开发---Tkinter的使用
- eclipse IDE配置最佳实践
- 文件系统测试工具IOZONE
- 【动漫宅也要写代码 基础篇】某队列的超电磁炮
- 工作中遇到的Android内存优化问题(1)
- Python scrapy run with Unhandled error in Deferred解决方案
- EventBus使用详解
- gcc参数详解
- typedef struct与struct
- 关于APK打包所报Messages错误
- 华为
- gcc -l参数和-L参数