pull/944/head
krahets 1 year ago
parent e181f9b491
commit 44ebc7748b

@ -4,9 +4,16 @@ comments: true
# 4.3   列表
**数组长度不可变导致实用性降低**。在实际中,我们可能事先无法确定需要存储多少数据,这使数组长度的选择变得困难。若长度过小,需要在持续添加数据时频繁扩容数组;若长度过大,则会造成内存空间的浪费
「列表 list」是一个抽象的数据结构概念它表示元素的有序集合支持元素访问、修改、添加、删除和遍历等操作无需使用者考虑容量限制的问题。列表可以基于链表或数组实现
为解决此问题,出现了一种被称为「动态数组 dynamic array」的数据结构即长度可变的数组也常被称为「列表 list」。列表基于数组实现继承了数组的优点并且可以在程序运行过程中动态扩容。我们可以在列表中自由地添加元素而无须担心超过容量限制。
- 链表天然可以被看作是一个列表,其支持元素增删查改操作,并且可以灵活动态扩容。
- 数组也支持元素增删查改,但由于其长度不可变,因此只能被看作是一个具有长度限制的列表。
当使用数组实现列表时,**长度不可变的性质会导致列表的实用性降低**。这是因为我们通常无法事先确定需要存储多少数据,从而难以选择合适的列表长度。若长度过小,则很可能无法满足使用需求;若长度过大,则会造成内存空间的浪费。
为解决此问题,我们可以使用「动态数组 dynamic array」来实现列表。它继承了数组的各项优点并且可以在程序运行过程中进行动态扩容。
实际上,**许多编程语言中的标准库提供的列表都是基于动态数组实现的**,例如 Python 中的 `list` 、Java 中的 `ArrayList` 、C++ 中的 `vector` 和 C# 中的 `List` 等。在接下来的讨论中,我们将把“列表”和“动态数组”视为等同的概念。
## 4.3.1   列表常用操作

@ -8,7 +8,7 @@ comments: true
表 13-2 列举了几个示例数据,包括输入数组和对应的所有排列。
<p align="center"> 表 13-2 &nbsp; 数组与链表的效率对比 </p>
<p align="center"> 表 13-2 &nbsp; 全排列示例 </p>
<div class="center-table" markdown>

@ -3284,11 +3284,11 @@ $$
```zig title="worst_best_time_complexity.zig"
// 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱
pub fn randomNumbers(comptime n: usize) [n]i32 {
fn randomNumbers(comptime n: usize) [n]i32 {
var nums: [n]i32 = undefined;
// 生成数组 nums = { 1, 2, 3, ..., n }
for (nums) |*num, i| {
num.* = @intCast(i32, i) + 1;
for (&nums, 0..) |*num, i| {
num.* = @as(i32, @intCast(i)) + 1;
}
// 随机打乱数组元素
const rand = std.crypto.random;
@ -3297,11 +3297,11 @@ $$
}
// 查找数组 nums 中数字 1 所在索引
pub fn findOne(nums: []i32) i32 {
for (nums) |num, i| {
fn findOne(nums: []i32) i32 {
for (nums, 0..) |num, i| {
// 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
// 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
if (num == 1) return @intCast(i32, i);
if (num == 1) return @intCast(i);
}
return -1;
}

@ -1119,7 +1119,7 @@ comments: true
=== "Zig"
```zig title="graph_adjacency_matrix.zig"
[class]{GraphAdjMat}-[func]{}
```
## 9.2.2 &nbsp; 基于邻接表的实现

Loading…
Cancel
Save