Polish the chapter of stack_and_queue, tree

This commit is contained in:
krahets
2023-04-10 23:59:22 +08:00
parent 1bbfa85e08
commit 236b9cadb1
10 changed files with 162 additions and 180 deletions

View File

@ -1,12 +1,12 @@
# 双向队列
对于队列,我们能在头部删除或在尾部添加元素,「双向队列 Deque」更加灵活,在其头部和尾部都能执行元素添加或删除操作。
对于队列,我们能在头部删除或在尾部添加元素。然而,「双向队列 Deque」提供了更高的灵活性,允许在头部和尾部执行元素添加或删除操作。
![双向队列的操作](deque.assets/deque_operations.png)
## 双向队列常用操作
双向队列的常用操作下表,方法名需根据语言来确定。
双向队列的常用操作下表所示,具体的方法名称需要根据所使用的编程语言来确定。
<div class="center-table" markdown>
@ -21,7 +21,7 @@
</div>
同地,我们可以直接使用编程语言实现的双向队列类。
地,我们可以直接使用编程语言中已实现的双向队列类。
=== "Java"
@ -285,15 +285,15 @@
## 双向队列实现 *
与队列类似,双向队列同样可以使用链表或数组来实现
双向队列的实现与队列类似,可以选择链表或数组作为底层数据结构
### 基于双向链表的实现
忆上节内容,由于可以方便地删除链表头节点(对应出队操作),以及在链表尾节点后添加新节点(对应入队操作),因此我们使用普通单向链表来实现队列
顾上一节内容,我们使用普通单向链表来实现队列,因为它可以方便地删除头节点(对应出队操作)和在尾节点后添加新节点(对应入队操作)。
双向队列头部和尾部都可以执行入队出队操作,换言之,双向队列的操作是“首尾对称”的,也需要实现另一个对称方向的操作。此,双向队列需要使用「双向链表」来实现
对于双向队列而言,头部和尾部都可以执行入队出队操作。换句话说,双向队列需要实现另一个对称方向的操作。此,我们采用「双向链表」作为双向队列的底层数据结构
我们将双向链表的头节点和尾节点分别看作双向队列的队首和队尾,并且实现在两端都能添加删除节点。
我们将双向链表的头节点和尾节点视为双向队列的队首和队尾,同时实现在两端添加删除节点的功能
=== "LinkedListDeque"
![基于链表实现双向队列的入队出队操作](deque.assets/linkedlist_deque.png)
@ -392,7 +392,7 @@
### 基于数组的实现
与基于数组实现队列类似,我们也可以使用环形数组来实现双向队列。在实现队列的基础上,增加实现“队首入队”和“队尾出队”方法即可
与基于数组实现队列类似,我们也可以使用环形数组来实现双向队列。在队列的实现基础上,仅需增加“队首入队”和“队尾出队”方法。
=== "ArrayDeque"
![基于数组实现双向队列的入队出队操作](deque.assets/array_deque.png)
@ -473,6 +473,6 @@
## 双向队列应用
双向队列同时表现出栈与队列的逻辑,**因此可以实现两者的所有应用,并且提供更高的自由度**。
双向队列兼具栈与队列的逻辑,**因此可以实现两者的所有应用场景,同时提供更高的自由度**。
我们知道,软件的“撤销”功能需要使用栈来实现系统把每一次更改操作 `push` 到栈中,然后通过 `pop` 实现撤销。然而,考虑到系统资源有限,软件一般会限制撤销的步数(例如仅允许保存 $50$ 步),那么当栈的长度 $> 50$ 时,软件需要在栈底(即队首)执行删除**但栈无法实现,此时就需要使用双向队列来替代栈**。注意,“撤销”的核心逻辑仍然栈的先入后出,只是双向队列可以更加灵活地实现。
我们知道,软件的“撤销”功能通常使用栈来实现系统将每次更改操作 `push` 到栈中,然后通过 `pop` 实现撤销。然而,考虑到系统资源的限制,软件通常会限制撤销的步数(例如仅允许保存 $50$ 步)当栈的长度超过 $50$ 时,软件需要在栈底(即队首)执行删除操作。**但栈无法实现该功能,此时就需要使用双向队列来替代栈**。注意,“撤销”的核心逻辑仍然遵循栈的先入后出原则,只是双向队列能够更加灵活地实现一些额外逻辑