双端队列

Java 并发工具包 java.util.concurrent 用户指南

陌路散爱 提交于 2019-12-01 00:08:04
译序 本指南根据 Jakob Jenkov 最新博客翻译, 请随时关注博客更新 本指南已做成中英文对照阅读版的 pdf 文档,有兴趣的朋友可以去 Java并发工具包java.util.concurrent用户指南中英文对照阅读版 进行下载。 1. java.util.concurrent - Java并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包。这个包包含有一系列能够让 Java 的并发编程变得更加简单轻松的类。在这个包被添加以前,你需要自己去动手实现自己的相关工具类。 本文我将带你一一认识 java.util.concurrent 包里的这些类,然后你可以尝试着如何在项目中使用它们。本文中我将使用 Java 6 版本,我不确定这和 Java 5 版本里的是否有一些差异。 我不会去解释关于 Java 并发的核心问题 - 其背后的原理,也就是说,如果你对那些东西感兴趣,参考 《Java 并发指南》 半成品 本文很大程度上还是个 “半成品”,所以当你发现一些被漏掉的类或接口时,请耐心等待。在我空闲的时候会把它们加进来的。 2. 阻塞队列BlockingQueue java.util.concurrent 包里的 BlockingQueue 接口表示一个线程安放入和提取实例的队列。本小节我将给你演示如何使用这个

看完这篇你还不知道这些队列,我这些图白作了

*爱你&永不变心* 提交于 2019-11-29 00:47:42
队列(queue)是一种采用先进先出(FIFO)策略的抽象数据结构,即最先进队列的数据元素,同样要最先出队列。队列跟我们排队买票一样,先来排队的肯定先买票,后来排队的的后买到票。队列如下图所示: 队列有两个重要的概念,一个叫队头,一个叫队尾,队头指向的是第一个元素,而队尾指向的是最后一个元素。队列跟栈一样也是访问受限制的,所以队列也只有两个主要的操作: 入队(enqueue)操作 和 出队(dequeue)操作 。入队操作就是将一个元素添加到队尾,出队操作就是从队头取出一个元素。 队列的底层实现可以用数组和链表,基于数组实现的队列叫作 顺序队列 ,基于链表实现的队列叫作 链式队列 ,下面我们分别用数组和链表来简单的实现这两种队列。 基于数组的队列 不管使用那种方式来实现队列,都需要定义两个指针分别指向队头和队尾,本文中我们用 head 指向队头, tail 指向队尾,后面的示例中这将默认使用这个,有特殊的地方我会进行说明,先来看看顺序队列的入队、出队操作。 图中可以看出,入队时,队尾往后移动,队头保持不变,出队是队头往后移动,队尾保持不变。入队、出队操作的逻辑都比较简单,可能你有疑问的地方是: 出队时为什么队头要往后移动而不是一直指向数组下标为 0 的位置? 为什么呢?如果我们保持队头一直指向数组下标为 0 的位置,那每次出队操作后,后面的数据都需要往前挪一位

CH134 双端队列 题解报告

℡╲_俬逩灬. 提交于 2019-11-27 15:38:23
题目传送门 【题目大意】 用若干个双端队列给$N$个整数排序,依次处理这$N$个数,对于每个数$A_i$,可以进行两种操作: 1.新建一个双端队列,并将$A_i$作为这个队列中唯一的数 2.把$A_i$从已有队列的队头或队尾入队 对所有的数处理完后,要求这些队列能够按照一定的顺序连接起来,得到一个非降的长度为$N$的序列,求最少需要多少个双端队列。 【思路分析】 我们把问题反过来思考,先把$N$个数从小到大排序,然后分成尽量少的几段,对应原问题中的合法双端队列。 易知一个结论,对于排序后每个位置的数原本的下标组成的序列$B$,如果一段满足单谷性质(即先递减后递增),那么这一段就对应原问题中的一个合法双端队列。(递减的一段相当于从队头插入,递增的一段相当于从队尾插入) 还要注意一点,就是如果存在相同的几个数,那么它们排序后的位置是随机的,可以看成一个整体来处理。如果这个整体中最小的下标大于前面的序列中最大的下标,那么满足递增;如果这个整体中最大的下标小于前面的序列中最小的下标,那么满足递减。 【代码实现】 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define g() getchar() 7 #define rg

双端队列Dque

时间秒杀一切 提交于 2019-11-27 14:13:14
双端队列的概念与数据结构   deque(也称为双端队列)是与队列类似的项的有序集合。它有两个端部,首部和尾部,并且项在集合中保持不变。   deque 特殊之处在于添加和删除项是非限制性的。可以在前面或后面添加新项。同样,可以从任一端移除现有项。在某种意义上,这种混合线性结构提供了单个数据结构中的栈和队列的所有能力。   Deque的抽象数据类型定义:Deque的抽象数据类型应该由以下结构和操作定义。其中元素可以从首部或尾部的任一端添加和移除。Deque操作如下: Dque() 创建一个空的新 deque。它不需要参数,并返回空的 deque。 lpush(item) 将一个新项添加到 deque 的首部。它需要 item 参数 并不返回任何内容。 rpush(item) 将一个新项添加到 deque 的尾部。它需要 item 参数并不返回任何内容。 lpop() 从 deque 中删除首项。它不需要参数并返回 item。deque 被修改。 rpop() 从 deque 中删除尾项。它不需要参数并返回 item。deque 被修改。 isEmpty() 测试 deque 是否为空。它不需要参数,并返回布尔值。 size() 返回 deque 中的项数。它不需要参数,并返回一个整数。   双端队列的定义    1 class Deque(object): 2 def __init

Beijing2011双端队列 题解

天涯浪子 提交于 2019-11-26 18:04:44
题目链接: bzoj2457 挺好的一道题。 想了挺长时间。。。 如果我们对于每一个读入的数据进行处理,判断每个数据应该放入哪一个队列,或者是应不应该再重新开一个队列,是非常困难的。因为在处理每一个数据时,由于我们不知道之后数据的情况,所以就不能确定当前数据的位置。而且通过观察也没有什么结论性的东西挖掘。。。(行吧我承认,仅仅是我想不出来而已。。或许真的存在呢。。。) 那么,我们应该换一种思路去解决:从问题的答案出发,寻找原数据与目标数据之间的联系。 首先,容易发现,每一个双端队列里的元素都是单调递增的,且它们的并集就是原数据从小到大排序后的结果(似乎说了一句废话。。。。),所以问题就转化为了:对于一个序列,将其分成若干个连续的子段,使得子段总数量最小。 由于双端队列只可以进行对头入队,队尾出队两种操作,所以对于最终答案的每一个子段,在某位置一定存在一个最小的下标,并且这个数的左边和右边的数的下标都是依次非递减的。 有了这个性质之后容易证明:我们只需要使从前往后的每一个子段包含的元素尽量多,就可以保证最终的子段的总个数最小。 那么做法就显而易见了:先对所有数据排序,同时保留所有数据对应至原数组的下标,然后从前往后寻找最长的“单谷函数”,最终得到的所有“单谷函数”的个数就是最终的答案。 其实问题到这里并没有结束。。我们忽略了相等元素的情况。对于相等的元素