Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/cs-basics/data-structure/linear-data-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,12 +297,32 @@ myStack.pop();//报错:java.lang.IllegalArgumentException: Stack is empty.
1. 可以设置一个标志变量 `flag`,当 `front==rear` 并且 `flag=0` 的时候队列为空,当`front==rear` 并且 `flag=1` 的时候队列为满。
2. 队列为空的时候就是 `front==rear` ,队列满的时候,我们保证数组还有一个空闲的位置,rear 就指向这个空闲位置,如下图所示,那么现在判断队列是否为满的条件就是:`(rear+1) % QueueSize==front` 。

#### 4.2.3 双端队列

**双端队列 (Deque)** 是一种在队列的两端都可以进行插入和删除操作的队列,相比单队列来说更加灵活。

一般来说,我们可以对双端队列进行 `addFirst`、`addLast`、`removeFirst` 和 `removeLast` 操作。

#### 4.2.4 优先队列

**优先队列 (Priority Queue)** 从底层结构上来讲并非线性的数据结构,它一般是由堆来实现的。

1. 在每个元素入队时,优先队列会将新元素其插入堆中并调整堆。
2. 在队头出队时,优先队列会返回堆顶元素并调整堆。

关于堆的具体实现可以看[堆](https://javaguide.cn/cs-basics/data-structure/heap.html)这一节。

总而言之,不论我们进行什么操作,优先队列都能按照**某种排序方式**进行一系列堆的相关操作,从而保证整个集合的**有序性**。

虽然优先队列的底层并非严格的线性结构,但是在我们使用的过程中,我们是感知不到**堆**的,从使用者的眼中优先队列可以被认为是一种线性的数据结构:一种会自动排序的线性队列。

### 4.3. 常见应用场景

当我们需要按照一定顺序来处理数据的时候可以考虑使用队列这个数据结构。

- **阻塞队列:** 阻塞队列可以看成在队列基础上加了阻塞操作的队列。当队列为空的时候,出队操作阻塞,当队列满的时候,入队操作阻塞。使用阻塞队列我们可以很容易实现“生产者 - 消费者“模型。
- **线程池中的请求/任务队列:** 线程池中没有空闲线程时,新的任务请求线程资源时,线程池该如何处理呢?答案是将这些请求放在队列中,当有空闲线程的时候,会循环中反复从队列中获取任务来执行。队列分为无界队列(基于链表)和有界队列(基于数组)。无界队列的特点就是可以一直入列,除非系统资源耗尽,比如:`FixedThreadPool` 使用无界队列 `LinkedBlockingQueue`。但是有界队列就不一样了,当队列满的话后面再有任务/请求就会拒绝,在 Java 中的体现就是会抛出`java.util.concurrent.RejectedExecutionException` 异常。
- 栈:双端队列天生便可以实现栈的全部功能(`push`、`pop` 和 `peek`),并且在Deque接口中已经实现了相关方法。Stack 类已经和 Vector 一样被遗弃,现在在 Java 中普遍使用双端队列(Deque)来实现栈。
- Linux 内核进程队列(按优先级排队)
- 现实生活中的派对,播放器上的播放列表;
- 消息队列
Expand Down