mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-21 02:56:11 +00:00
build
This commit is contained in:
@@ -159,6 +159,12 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title=""
|
||||
|
||||
```
|
||||
|
||||
!!! question "尾节点指向什么?"
|
||||
|
||||
我们将链表的最后一个节点称为「尾节点」,其指向的是“空”,在 Java, C++, Python 中分别记为 $\text{null}$ , $\text{nullptr}$ , $\text{None}$ 。在不引起歧义的前提下,本书都使用 $\text{null}$ 来表示空。
|
||||
@@ -339,6 +345,12 @@ comments: true
|
||||
n3.next = &n4;
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="linked_list.dart"
|
||||
|
||||
```
|
||||
|
||||
## 4.2.1. 链表优点
|
||||
|
||||
**链表中插入与删除节点的操作效率高**。例如,如果我们想在链表中间的两个节点 `A` , `B` 之间插入一个新节点 `P` ,我们只需要改变两个节点指针即可,时间复杂度为 $O(1)$ ;相比之下,数组的插入操作效率要低得多。
|
||||
@@ -456,6 +468,17 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="linked_list.dart"
|
||||
/* 在链表的节点 n0 之后插入节点 P */
|
||||
void insert(ListNode n0, ListNode P) {
|
||||
ListNode? n1 = n0.next;
|
||||
P.next = n1;
|
||||
n0.next = P;
|
||||
}
|
||||
```
|
||||
|
||||
在链表中删除节点也非常方便,只需改变一个节点的指针即可。如下图所示,尽管在删除操作完成后,节点 `P` 仍然指向 `n1` ,但实际上 `P` 已经不再属于此链表,因为遍历此链表时无法访问到 `P` 。
|
||||
|
||||

|
||||
@@ -608,6 +631,18 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="linked_list.dart"
|
||||
/* 删除链表的节点 n0 之后的首个节点 */
|
||||
void remove(ListNode n0) {
|
||||
if (n0.next == null) return;
|
||||
ListNode P = n0.next!;
|
||||
ListNode? n1 = P.next;
|
||||
n0.next = n1;
|
||||
}
|
||||
```
|
||||
|
||||
## 4.2.2. 链表缺点
|
||||
|
||||
**链表访问节点效率较低**。如上节所述,数组可以在 $O(1)$ 时间下访问任意元素。然而,链表无法直接访问任意节点,这是因为系统需要从头节点出发,逐个向后遍历直至找到目标节点。例如,若要访问链表索引为 `index`(即第 `index + 1` 个)的节点,则需要向后遍历 `index` 轮。
|
||||
@@ -755,6 +790,19 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="linked_list.dart"
|
||||
/* 访问链表中索引为 index 的节点 */
|
||||
ListNode? access(ListNode? head, int index) {
|
||||
for (var i = 0; i < index; i++) {
|
||||
if (head == null) return null;
|
||||
head = head.next;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
```
|
||||
|
||||
**链表的内存占用较大**。链表以节点为单位,每个节点除了保存值之外,还需额外保存指针(引用)。这意味着在相同数据量的情况下,链表比数组需要占用更多的内存空间。
|
||||
|
||||
## 4.2.3. 链表常用操作
|
||||
@@ -924,6 +972,23 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="linked_list.dart"
|
||||
/* 在链表中查找值为 target 的首个节点 */
|
||||
int find(ListNode? head, int target) {
|
||||
int index = 0;
|
||||
while (head != null) {
|
||||
if (head.val == target) {
|
||||
return index;
|
||||
}
|
||||
head = head.next;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
## 4.2.4. 常见链表类型
|
||||
|
||||
**单向链表**。即上述介绍的普通链表。单向链表的节点包含值和指向下一节点的指针(引用)两项数据。我们将首个节点称为头节点,将最后一个节点成为尾节点,尾节点指向 $\text{null}$ 。
|
||||
@@ -1091,6 +1156,12 @@ comments: true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title=""
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 常见链表种类 </p>
|
||||
|
||||
Reference in New Issue
Block a user