diff --git a/chapter_array_and_linkedlist/list.md b/chapter_array_and_linkedlist/list.md index 2a83b79fd..7ab5c11a9 100755 --- a/chapter_array_and_linkedlist/list.md +++ b/chapter_array_and_linkedlist/list.md @@ -1562,9 +1562,9 @@ comments: true const Self = @This(); nums: []T = undefined, // 数组(存储列表元素) - numsCapacity: usize = 10, // 列表容量 - numSize: usize = 0, // 列表长度(即当前元素数量) - extendRatio: usize = 2, // 每次列表扩容的倍数 + nums_capacity: usize = 10, // 列表容量 + num_size: usize = 0, // 列表长度(即当前元素数量) + extend_ratio: usize = 2, // 每次列表扩容的倍数 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -1574,7 +1574,7 @@ comments: true self.mem_arena = std.heap.ArenaAllocator.init(allocator); self.mem_allocator = self.mem_arena.?.allocator(); } - self.nums = try self.mem_allocator.alloc(T, self.numsCapacity); + self.nums = try self.mem_allocator.alloc(T, self.nums_capacity); std.mem.set(T, self.nums, @as(T, 0)); } @@ -1586,12 +1586,12 @@ comments: true // 获取列表长度(即当前元素数量) pub fn size(self: *Self) usize { - return self.numSize; + return self.num_size; } // 获取列表容量 pub fn capacity(self: *Self) usize { - return self.numsCapacity; + return self.nums_capacity; } // 访问元素 @@ -1614,7 +1614,7 @@ comments: true if (self.size() == self.capacity()) try self.extendCapacity(); self.nums[self.size()] = num; // 更新元素数量 - self.numSize += 1; + self.num_size += 1; } // 中间插入元素 @@ -1629,7 +1629,7 @@ comments: true } self.nums[index] = num; // 更新元素数量 - self.numSize += 1; + self.num_size += 1; } // 删除元素 @@ -1642,22 +1642,22 @@ comments: true self.nums[j] = self.nums[j + 1]; } // 更新元素数量 - self.numSize -= 1; + self.num_size -= 1; // 返回被删除元素 return num; } // 列表扩容 pub fn extendCapacity(self: *Self) !void { - // 新建一个长度为 size * extendRatio 的数组,并将原数组拷贝到新数组 - var newCapacity = self.capacity() * self.extendRatio; + // 新建一个长度为 size * extend_ratio 的数组,并将原数组拷贝到新数组 + var newCapacity = self.capacity() * self.extend_ratio; var extend = try self.mem_allocator.alloc(T, newCapacity); std.mem.set(T, extend, @as(T, 0)); // 将原数组中的所有元素复制到新数组 std.mem.copy(T, extend, self.nums); self.nums = extend; // 更新列表容量 - self.numsCapacity = newCapacity; + self.nums_capacity = newCapacity; } // 将列表转换为数组 diff --git a/chapter_graph/graph_operations.md b/chapter_graph/graph_operations.md index 5abfaed8c..d7010ecec 100644 --- a/chapter_graph/graph_operations.md +++ b/chapter_graph/graph_operations.md @@ -952,7 +952,9 @@ comments: true /* 打印邻接表 */ void print() { cout << "邻接表 =" << endl; - for (auto& [key, vec] : adjList) { + for (auto& adj : adjList) { + const auto& key= adj.first; + const auto& vec = adj.second; cout << key->val << ": "; PrintUtil::printVector(vetsToVals(vec)); } diff --git a/chapter_hashing/hash_collision.md b/chapter_hashing/hash_collision.md index 632d2fd14..64db37815 100644 --- a/chapter_hashing/hash_collision.md +++ b/chapter_hashing/hash_collision.md @@ -6,15 +6,15 @@ comments: true 理想情况下,哈希函数应该为每个输入产生唯一的输出,使得 key 和 value 一一对应。而实际上,往往存在向哈希函数输入不同的 key 而产生相同输出的情况,这种情况被称为「哈希冲突 Hash Collision」。哈希冲突会导致查询结果错误,从而严重影响哈希表的可用性。 -那么,为什么会出现哈希冲突呢?本质上看,**由于哈希函数的输入空间往往远大于输出空间**,因此不可避免地会出现多个输入产生相同输出的情况,即为哈希冲突。比如,输入空间是全体整数,输出空间是一个固定大小的桶(数组)的索引范围,那么必定会有多个整数同时映射到一个桶索引。 +那么,为什么会出现哈希冲突呢?本质上看,**由于哈希函数的输入空间往往远大于输出空间**,因此不可避免地会出现多个输入产生相同输出的情况,即为哈希冲突。比如,输入空间是全体整数,输出空间是一个固定大小的数组,那么必定会有多个整数映射到同一个数组索引。 -为了缓解哈希冲突,一方面,**我们可以通过哈希表扩容来减小冲突概率**。极端情况下,当输入空间和输出空间大小相等时,哈希表就等价于数组了,可谓“大力出奇迹”。 +为了缓解哈希冲突,一方面,**我们可以通过哈希表扩容来减小冲突概率**。极端情况下,当输入空间和输出空间大小相等时,哈希表就等价于数组了,每个 key 都对应唯一的数组索引,可谓“大力出奇迹”。 -另一方面,**考虑通过优化哈希表的表示方式以缓解哈希冲突**,常见的方法有「链式地址」和「开放寻址」。 +另一方面,**考虑通过优化哈希表的来缓解哈希冲突**,常见的方法有「链式地址」和「开放寻址」。 ## 6.2.1.   哈希表扩容 -「负载因子 Load Factor」定义为 **哈希表中元素数量除以桶槽数量(即数组大小)**,代表哈希冲突的严重程度。 +「负载因子 Load Factor」定义为 **哈希表中元素数量除以桶数量(即数组大小)**,代表哈希冲突的严重程度。 **负载因子常用作哈希表扩容的触发条件**。比如在 Java 中,当负载因子 $> 0.75$ 时则触发扩容,将 HashMap 大小扩充至原先的 $2$ 倍。 @@ -22,7 +22,7 @@ comments: true ## 6.2.2.   链式地址 -在原始哈希表中,桶内的每个地址只能存储一个元素(即键值对)。**考虑将单个元素转化成一个链表,将所有冲突元素都存储在一个链表中**。 +在原始哈希表中,每个桶只能存储一个元素(即键值对)。**考虑将单个元素转化成一个链表,将所有冲突元素都存储在一个链表中**。 ![链式地址](hash_collision.assets/hash_collision_chaining.png) @@ -30,7 +30,7 @@ comments: true 链式地址下,哈希表操作方法为: -- **查询元素**:先将 key 输入到哈希函数得到桶内索引,即可访问链表头结点,再通过遍历链表查找对应 value 。 +- **查询元素**:输入 key ,经过哈希函数得到数组索引,即可访问链表头结点,再通过遍历链表并对比 key 来查找键值对。 - **添加元素**:先通过哈希函数访问链表头部,再将结点(即键值对)添加到链表头部即可。 - **删除元素**:同样先根据哈希函数结果访问链表头部,再遍历链表查找对应结点,删除之即可。 @@ -62,8 +62,8 @@ comments: true 线性探测存在以下缺陷: -- **不能直接删除元素**。删除元素会导致桶内出现一个空位,在查找其他元素时,该空位有可能导致程序认为元素不存在(即上述第 `2.` 种情况)。因此需要借助一个标志位来标记删除元素。 -- **容易产生聚集**。桶内被占用的连续位置越长,这些连续位置发生哈希冲突的可能性越大,从而进一步促进这一位置的“聚堆生长”,最终导致增删查改操作效率的劣化。 +- **不能直接删除元素**。删除元素会导致数组内出现一个空位,在查找其他元素时,该空位有可能导致程序认为元素不存在(即上述第 `2.` 种情况)。因此需要借助一个标志位来标记删除元素。 +- **容易产生聚集**。数组内被占用的连续位置越长,这些连续位置发生哈希冲突的可能性越大,从而进一步促进这一位置的“聚堆生长”,最终导致增删查改操作效率的劣化。 ### 多次哈希 @@ -83,3 +83,5 @@ comments: true Java 采用「链式地址」。在 JDK 1.8 之后,HashMap 内数组长度大于 64 时,长度大于 8 的链表会被转化为「红黑树」,以提升查找性能。 Python 采用「开放寻址」。字典 dict 使用伪随机数进行探测。 + + Golang 采用「链式地址」。Go 规定每个桶最多存储 8 个键值对,超出容量则连接一个溢出桶;当溢出桶过多时,会执行一次特殊的等量扩容操作,以保证性能。 diff --git a/chapter_hashing/hash_map.md b/chapter_hashing/hash_map.md index ee39192d1..2a79427da 100755 --- a/chapter_hashing/hash_map.md +++ b/chapter_hashing/hash_map.md @@ -396,14 +396,16 @@ comments: true ## 6.1.3.   哈希函数 -哈希表中存储元素的数据结构被称为「桶 Bucket」,底层实现可能是数组、链表、二叉树(红黑树),或是它们的组合。 +哈希表的底层实现是数组,并且可能包含链表、二叉树(红黑树)等数据结构,以提升查询性能(下节会讨论)。 -最简单地,**我们可以仅用一个「数组」来实现哈希表**。首先,将所有 value 放入数组中,那么每个 value 在数组中都有唯一的「索引」。显然,访问 value 需要给定索引,而为了 **建立 key 和索引之间的映射关系**,我们需要使用「哈希函数 Hash Function」。 +首先考虑最简单的情况,**即仅用一个「数组」来实现哈希表**。根据习惯,我们将数组中的每个空位称为「桶 Bucket」,用于存储键值对。 -设数组为 `bucket` ,哈希函数为 `f(x)` ,输入键为 `key` 。那么获取 value 的步骤为: +我们将键值对 key, value 包装成一个类 `Entry` ,并将所有 `Entry` 都放入数组中,那么每个 `Entry` 在数组中都有唯一的索引。显然,访问 `Entry` 需要给定索引,而为了 **建立 key 和索引之间的映射关系**,我们需要使用「哈希函数 Hash Function」。 + +具体地,设数组为 `buckets` ,哈希函数为 `f(x)` ,输入键为 `key` 。那么获取 value 的步骤为: 1. 通过哈希函数计算出索引,即 `index = f(key)` ; -2. 通过索引在数组中获取值,即 `value = bucket[index]` ; +2. 通过索引在数组中获取键值对,即 `Entry = buckets[index]` ; 以上述学生数据 `key 学号 -> value 姓名` 为例,我们可以将「哈希函数」设计为 @@ -411,6 +413,8 @@ $$ f(x) = x \% 100 $$ +如下图所示,输入一个学号 key ,经过哈希函数计算就能访问到对应的姓名 value 。 + ![简单哈希函数示例](hash_map.assets/hash_function.png)

Fig. 简单哈希函数示例

@@ -430,12 +434,12 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - private List bucket; + private List buckets; public ArrayHashMap() { // 初始化一个长度为 100 的桶(数组) - bucket = new ArrayList<>(); + buckets = new ArrayList<>(); for (int i = 0; i < 100; i++) { - bucket.add(null); + buckets.add(null); } } @@ -448,7 +452,7 @@ $$ /* 查询操作 */ public String get(int key) { int index = hashFunc(key); - Entry pair = bucket.get(index); + Entry pair = buckets.get(index); if (pair == null) return null; return pair.val; } @@ -457,20 +461,20 @@ $$ public void put(int key, String val) { Entry pair = new Entry(key, val); int index = hashFunc(key); - bucket.set(index, pair); + buckets.set(index, pair); } /* 删除操作 */ public void remove(int key) { int index = hashFunc(key); // 置为 null ,代表删除 - bucket.set(index, null); + buckets.set(index, null); } /* 获取所有键值对 */ public List entrySet() { List entrySet = new ArrayList<>(); - for (Entry pair : bucket) { + for (Entry pair : buckets) { if (pair != null) entrySet.add(pair); } @@ -480,7 +484,7 @@ $$ /* 获取所有键 */ public List keySet() { List keySet = new ArrayList<>(); - for (Entry pair : bucket) { + for (Entry pair : buckets) { if (pair != null) keySet.add(pair.key); } @@ -490,7 +494,7 @@ $$ /* 获取所有值 */ public List valueSet() { List valueSet = new ArrayList<>(); - for (Entry pair : bucket) { + for (Entry pair : buckets) { if (pair != null) valueSet.add(pair.val); } @@ -523,11 +527,11 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { private: - vector bucket; + vector buckets; public: ArrayHashMap() { // 初始化一个长度为 100 的桶(数组) - bucket= vector(100); + buckets= vector(100); } /* 哈希函数 */ @@ -539,7 +543,7 @@ $$ /* 查询操作 */ string get(int key) { int index = hashFunc(key); - Entry* pair = bucket[index]; + Entry* pair = buckets[index]; if (pair == nullptr) return nullptr; return pair->val; @@ -549,20 +553,20 @@ $$ void put(int key, string val) { Entry* pair = new Entry(key, val); int index = hashFunc(key); - bucket[index] = pair; + buckets[index] = pair; } /* 删除操作 */ void remove(int key) { int index = hashFunc(key); // 置为 nullptr ,代表删除 - bucket[index] = nullptr; + buckets[index] = nullptr; } /* 获取所有键值对 */ vector entrySet() { vector entrySet; - for (Entry* pair: bucket) { + for (Entry* pair: buckets) { if (pair != nullptr) { entrySet.push_back(pair); } @@ -573,7 +577,7 @@ $$ /* 获取所有键 */ vector keySet() { vector keySet; - for (Entry* pair: bucket) { + for (Entry* pair: buckets) { if (pair != nullptr) { keySet.push_back(pair->key); } @@ -584,7 +588,7 @@ $$ /* 获取所有值 */ vector valueSet() { vector valueSet; - for (Entry* pair: bucket) { + for (Entry* pair: buckets) { if (pair != nullptr){ valueSet.push_back(pair->val); } @@ -615,7 +619,7 @@ $$ def __init__(self): """ 构造方法 """ # 初始化一个长度为 100 的桶(数组) - self.bucket: List[Optional[Entry]] = [None] * 100 + self.buckets: List[Optional[Entry]] = [None] * 100 def hash_func(self, key: int) -> int: """ 哈希函数 """ @@ -625,7 +629,7 @@ $$ def get(self, key: int) -> str: """ 查询操作 """ index: int = self.hash_func(key) - pair: Entry = self.bucket[index] + pair: Entry = self.buckets[index] if pair is None: return None return pair.val @@ -634,18 +638,18 @@ $$ """ 添加操作 """ pair = Entry(key, val) index: int = self.hash_func(key) - self.bucket[index] = pair + self.buckets[index] = pair def remove(self, key: int) -> None: """ 删除操作 """ index: int = self.hash_func(key) # 置为 None ,代表删除 - self.bucket[index] = None + self.buckets[index] = None def entry_set(self) -> List[Entry]: """ 获取所有键值对 """ result: List[Entry] = [] - for pair in self.bucket: + for pair in self.buckets: if pair is not None: result.append(pair) return result @@ -653,7 +657,7 @@ $$ def key_set(self) -> List[int]: """ 获取所有键 """ result: List[int] = [] - for pair in self.bucket: + for pair in self.buckets: if pair is not None: result.append(pair.key) return result @@ -661,14 +665,14 @@ $$ def value_set(self) -> List[str]: """ 获取所有值 """ result: List[str] = [] - for pair in self.bucket: + for pair in self.buckets: if pair is not None: result.append(pair.val) return result def print(self) -> None: """ 打印哈希表 """ - for pair in self.bucket: + for pair in self.buckets: if pair is not None: print(pair.key, "->", pair.val) ``` @@ -684,14 +688,14 @@ $$ /* 基于数组简易实现的哈希表 */ type arrayHashMap struct { - bucket []*entry + buckets []*entry } /* 初始化哈希表 */ func newArrayHashMap() *arrayHashMap { // 初始化一个长度为 100 的桶(数组) - bucket := make([]*entry, 100) - return &arrayHashMap{bucket: bucket} + buckets := make([]*entry, 100) + return &arrayHashMap{buckets: buckets} } /* 哈希函数 */ @@ -703,7 +707,7 @@ $$ /* 查询操作 */ func (a *arrayHashMap) get(key int) string { index := a.hashFunc(key) - pair := a.bucket[index] + pair := a.buckets[index] if pair == nil { return "Not Found" } @@ -714,20 +718,20 @@ $$ func (a *arrayHashMap) put(key int, val string) { pair := &entry{key: key, val: val} index := a.hashFunc(key) - a.bucket[index] = pair + a.buckets[index] = pair } /* 删除操作 */ func (a *arrayHashMap) remove(key int) { index := a.hashFunc(key) // 置为 nil ,代表删除 - a.bucket[index] = nil + a.buckets[index] = nil } /* 获取所有键对 */ func (a *arrayHashMap) entrySet() []*entry { var pairs []*entry - for _, pair := range a.bucket { + for _, pair := range a.buckets { if pair != nil { pairs = append(pairs, pair) } @@ -738,7 +742,7 @@ $$ /* 获取所有键 */ func (a *arrayHashMap) keySet() []int { var keys []int - for _, pair := range a.bucket { + for _, pair := range a.buckets { if pair != nil { keys = append(keys, pair.key) } @@ -749,7 +753,7 @@ $$ /* 获取所有值 */ func (a *arrayHashMap) valueSet() []string { var values []string - for _, pair := range a.bucket { + for _, pair := range a.buckets { if pair != nil { values = append(values, pair.val) } @@ -759,7 +763,7 @@ $$ /* 打印哈希表 */ func (a *arrayHashMap) print() { - for _, pair := range a.bucket { + for _, pair := range a.buckets { if pair != nil { fmt.Println(pair.key, "->", pair.val) } @@ -780,10 +784,10 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - #bucket; + #buckets; constructor() { // 初始化一个长度为 100 的桶(数组) - this.#bucket = new Array(100).fill(null); + this.#buckets = new Array(100).fill(null); } /* 哈希函数 */ @@ -794,7 +798,7 @@ $$ /* 查询操作 */ get(key) { let index = this.#hashFunc(key); - let entry = this.#bucket[index]; + let entry = this.#buckets[index]; if (entry === null) return null; return entry.val; } @@ -802,22 +806,22 @@ $$ /* 添加操作 */ set(key, val) { let index = this.#hashFunc(key); - this.#bucket[index] = new Entry(key, val); + this.#buckets[index] = new Entry(key, val); } /* 删除操作 */ delete(key) { let index = this.#hashFunc(key); // 置为 null ,代表删除 - this.#bucket[index] = null; + this.#buckets[index] = null; } /* 获取所有键值对 */ entries() { let arr = []; - for (let i = 0; i < this.#bucket.length; i++) { - if (this.#bucket[i]) { - arr.push(this.#bucket[i]); + for (let i = 0; i < this.#buckets.length; i++) { + if (this.#buckets[i]) { + arr.push(this.#buckets[i]); } } return arr; @@ -826,9 +830,9 @@ $$ /* 获取所有键 */ keys() { let arr = []; - for (let i = 0; i < this.#bucket.length; i++) { - if (this.#bucket[i]) { - arr.push(this.#bucket[i]?.key); + for (let i = 0; i < this.#buckets.length; i++) { + if (this.#buckets[i]) { + arr.push(this.#buckets[i]?.key); } } return arr; @@ -837,9 +841,9 @@ $$ /* 获取所有值 */ values() { let arr = []; - for (let i = 0; i < this.#bucket.length; i++) { - if (this.#bucket[i]) { - arr.push(this.#bucket[i]?.val); + for (let i = 0; i < this.#buckets.length; i++) { + if (this.#buckets[i]) { + arr.push(this.#buckets[i]?.val); } } return arr; @@ -873,11 +877,11 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - private readonly bucket: (Entry | null)[]; + private readonly buckets: (Entry | null)[]; constructor() { // 初始化一个长度为 100 的桶(数组) - this.bucket = (new Array(100)).fill(null); + this.buckets = (new Array(100)).fill(null); } /* 哈希函数 */ @@ -888,7 +892,7 @@ $$ /* 查询操作 */ public get(key: number): string | null { let index = this.hashFunc(key); - let entry = this.bucket[index]; + let entry = this.buckets[index]; if (entry === null) return null; return entry.val; } @@ -896,22 +900,22 @@ $$ /* 添加操作 */ public set(key: number, val: string) { let index = this.hashFunc(key); - this.bucket[index] = new Entry(key, val); + this.buckets[index] = new Entry(key, val); } /* 删除操作 */ public delete(key: number) { let index = this.hashFunc(key); // 置为 null ,代表删除 - this.bucket[index] = null; + this.buckets[index] = null; } /* 获取所有键值对 */ public entries(): (Entry | null)[] { let arr: (Entry | null)[] = []; - for (let i = 0; i < this.bucket.length; i++) { - if (this.bucket[i]) { - arr.push(this.bucket[i]); + for (let i = 0; i < this.buckets.length; i++) { + if (this.buckets[i]) { + arr.push(this.buckets[i]); } } return arr; @@ -920,9 +924,9 @@ $$ /* 获取所有键 */ public keys(): (number | undefined)[] { let arr: (number | undefined)[] = []; - for (let i = 0; i < this.bucket.length; i++) { - if (this.bucket[i]) { - arr.push(this.bucket[i]?.key); + for (let i = 0; i < this.buckets.length; i++) { + if (this.buckets[i]) { + arr.push(this.buckets[i]?.key); } } return arr; @@ -931,9 +935,9 @@ $$ /* 获取所有值 */ public values(): (string | undefined)[] { let arr: (string | undefined)[] = []; - for (let i = 0; i < this.bucket.length; i++) { - if (this.bucket[i]) { - arr.push(this.bucket[i]?.val); + for (let i = 0; i < this.buckets.length; i++) { + if (this.buckets[i]) { + arr.push(this.buckets[i]?.val); } } return arr; @@ -976,14 +980,14 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - private List bucket; + private List buckets; public ArrayHashMap() { // 初始化一个长度为 100 的桶(数组) - bucket = new(); + buckets = new(); for (int i = 0; i < 100; i++) { - bucket.Add(null); + buckets.Add(null); } } @@ -998,7 +1002,7 @@ $$ public String? get(int key) { int index = hashFunc(key); - Entry? pair = bucket[index]; + Entry? pair = buckets[index]; if (pair == null) return null; return pair.val; } @@ -1008,7 +1012,7 @@ $$ { Entry pair = new Entry(key, val); int index = hashFunc(key); - bucket[index] = pair; + buckets[index] = pair; } /* 删除操作 */ @@ -1016,14 +1020,14 @@ $$ { int index = hashFunc(key); // 置为 null ,代表删除 - bucket[index] = null; + buckets[index] = null; } /* 获取所有键值对 */ public List entrySet() { List entrySet = new(); - foreach (Entry? pair in bucket) + foreach (Entry? pair in buckets) { if (pair != null) entrySet.Add(pair); @@ -1035,7 +1039,7 @@ $$ public List keySet() { List keySet = new(); - foreach (Entry? pair in bucket) + foreach (Entry? pair in buckets) { if (pair != null) keySet.Add(pair.key); @@ -1047,7 +1051,7 @@ $$ public List valueSet() { List valueSet = new(); - foreach (Entry? pair in bucket) + foreach (Entry? pair in buckets) { if (pair != null) valueSet.Add(pair.val); @@ -1082,12 +1086,12 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - private var bucket: [Entry?] = [] + private var buckets: [Entry?] = [] init() { // 初始化一个长度为 100 的桶(数组) for _ in 0 ..< 100 { - bucket.append(nil) + buckets.append(nil) } } @@ -1100,7 +1104,7 @@ $$ /* 查询操作 */ func get(key: Int) -> String? { let index = hashFunc(key: key) - let pair = bucket[index] + let pair = buckets[index] return pair?.val } @@ -1108,20 +1112,20 @@ $$ func put(key: Int, val: String) { let pair = Entry(key: key, val: val) let index = hashFunc(key: key) - bucket[index] = pair + buckets[index] = pair } /* 删除操作 */ func remove(key: Int) { let index = hashFunc(key: key) // 置为 nil ,代表删除 - bucket[index] = nil + buckets[index] = nil } /* 获取所有键值对 */ func entrySet() -> [Entry] { var entrySet: [Entry] = [] - for pair in bucket { + for pair in buckets { if let pair = pair { entrySet.append(pair) } @@ -1132,7 +1136,7 @@ $$ /* 获取所有键 */ func keySet() -> [Int] { var keySet: [Int] = [] - for pair in bucket { + for pair in buckets { if let pair = pair { keySet.append(pair.key) } @@ -1143,7 +1147,7 @@ $$ /* 获取所有值 */ func valueSet() -> [String] { var valueSet: [String] = [] - for pair in bucket { + for pair in buckets { if let pair = pair { valueSet.append(pair.val) } @@ -1179,7 +1183,7 @@ $$ // 基于数组简易实现的哈希表 fn ArrayHashMap(comptime T: type) type { return struct { - bucket: ?std.ArrayList(?T) = null, + buckets: ?std.ArrayList(?T) = null, mem_allocator: std.mem.Allocator = undefined, const Self = @This(); @@ -1188,16 +1192,16 @@ $$ pub fn init(self: *Self, allocator: std.mem.Allocator) !void { self.mem_allocator = allocator; // 初始化一个长度为 100 的桶(数组) - self.bucket = std.ArrayList(?T).init(self.mem_allocator); + self.buckets = std.ArrayList(?T).init(self.mem_allocator); var i: i32 = 0; while (i < 100) : (i += 1) { - try self.bucket.?.append(null); + try self.buckets.?.append(null); } } // 析构方法 pub fn deinit(self: *Self) void { - if (self.bucket != null) self.bucket.?.deinit(); + if (self.buckets != null) self.buckets.?.deinit(); } // 哈希函数 @@ -1209,7 +1213,7 @@ $$ // 查询操作 pub fn get(self: *Self, key: usize) []const u8 { var index = hashFunc(key); - var pair = self.bucket.?.items[index]; + var pair = self.buckets.?.items[index]; return pair.?.val; } @@ -1217,20 +1221,20 @@ $$ pub fn put(self: *Self, key: usize, val: []const u8) !void { var pair = Entry.init(key, val); var index = hashFunc(key); - self.bucket.?.items[index] = pair; + self.buckets.?.items[index] = pair; } // 删除操作 pub fn remove(self: *Self, key: usize) !void { var index = hashFunc(key); // 置为 null ,代表删除 - self.bucket.?.items[index] = null; + self.buckets.?.items[index] = null; } // 获取所有键值对 pub fn entrySet(self: *Self) !*std.ArrayList(T) { var entry_set = std.ArrayList(T).init(self.mem_allocator); - for (self.bucket.?.items) |item| { + for (self.buckets.?.items) |item| { if (item == null) continue; try entry_set.append(item.?); } @@ -1240,7 +1244,7 @@ $$ // 获取所有键 pub fn keySet(self: *Self) !*std.ArrayList(usize) { var key_set = std.ArrayList(usize).init(self.mem_allocator); - for (self.bucket.?.items) |item| { + for (self.buckets.?.items) |item| { if (item == null) continue; try key_set.append(item.?.key); } @@ -1250,7 +1254,7 @@ $$ // 获取所有值 pub fn valueSet(self: *Self) !*std.ArrayList([]const u8) { var value_set = std.ArrayList([]const u8).init(self.mem_allocator); - for (self.bucket.?.items) |item| { + for (self.buckets.?.items) |item| { if (item == null) continue; try value_set.append(item.?.val); } diff --git a/chapter_heap/build_heap.md b/chapter_heap/build_heap.md index 15e8e6845..d9703dea6 100644 --- a/chapter_heap/build_heap.md +++ b/chapter_heap/build_heap.md @@ -141,10 +141,10 @@ comments: true ```zig title="my_heap.zig" // 构造方法,根据输入列表建堆 fn init(self: *Self, allocator: std.mem.Allocator, nums: []const T) !void { - if (self.maxHeap != null) return; - self.maxHeap = std.ArrayList(T).init(allocator); + if (self.max_heap != null) return; + self.max_heap = std.ArrayList(T).init(allocator); // 将列表元素原封不动添加进堆 - try self.maxHeap.?.appendSlice(nums); + try self.max_heap.?.appendSlice(nums); // 堆化除叶结点以外的其他所有结点 var i: usize = parent(self.size() - 1) + 1; while (i > 0) : (i -= 1) { diff --git a/chapter_heap/heap.md b/chapter_heap/heap.md index 9fe8f15c6..88b993af0 100644 --- a/chapter_heap/heap.md +++ b/chapter_heap/heap.md @@ -594,7 +594,7 @@ comments: true ```zig title="my_heap.zig" // 访问堆顶元素 fn peek(self: *Self) T { - return self.maxHeap.?.items[0]; + return self.max_heap.?.items[0]; } ``` @@ -855,7 +855,7 @@ comments: true // 元素入堆 fn push(self: *Self, val: T) !void { // 添加结点 - try self.maxHeap.?.append(val); + try self.max_heap.?.append(val); // 从底至顶堆化 try self.siftUp(self.size() - 1); } @@ -867,7 +867,7 @@ comments: true // 获取结点 i 的父结点 var p = parent(i); // 当“越过根结点”或“结点无需修复”时,结束堆化 - if (p < 0 or self.maxHeap.?.items[i] <= self.maxHeap.?.items[p]) break; + if (p < 0 or self.max_heap.?.items[i] <= self.max_heap.?.items[p]) break; // 交换两结点 try self.swap(i, p); // 循环向上堆化 @@ -1247,7 +1247,7 @@ comments: true // 交换根结点与最右叶结点(即交换首元素与尾元素) try self.swap(0, self.size() - 1); // 删除结点 - var val = self.maxHeap.?.pop(); + var val = self.max_heap.?.pop(); // 从顶至底堆化 try self.siftDown(0); // 返回堆顶元素 @@ -1262,8 +1262,8 @@ comments: true var l = left(i); var r = right(i); var ma = i; - if (l < self.size() and self.maxHeap.?.items[l] > self.maxHeap.?.items[ma]) ma = l; - if (r < self.size() and self.maxHeap.?.items[r] > self.maxHeap.?.items[ma]) ma = r; + if (l < self.size() and self.max_heap.?.items[l] > self.max_heap.?.items[ma]) ma = l; + if (r < self.size() and self.max_heap.?.items[r] > self.max_heap.?.items[ma]) ma = r; // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; // 交换两结点 diff --git a/chapter_stack_and_queue/queue.md b/chapter_stack_and_queue/queue.md index 1e2353341..b06eef8e2 100755 --- a/chapter_stack_and_queue/queue.md +++ b/chapter_stack_and_queue/queue.md @@ -1541,7 +1541,7 @@ comments: true nums: []T = undefined, // 用于存储队列元素的数组 cap: usize = 0, // 队列容量 front: usize = 0, // 队首指针,指向队首元素 - queSize: usize = 0, // 尾指针,指向队尾 + 1 + que_size: usize = 0, // 尾指针,指向队尾 + 1 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -1569,12 +1569,12 @@ comments: true // 获取队列的长度 pub fn size(self: *Self) usize { - return self.queSize; + return self.que_size; } // 判断队列是否为空 pub fn isEmpty(self: *Self) bool { - return self.queSize == 0; + return self.que_size == 0; } // 入队 @@ -1585,10 +1585,10 @@ comments: true } // 计算尾指针,指向队尾索引 + 1 // 通过取余操作,实现 rear 越过数组尾部后回到头部 - var rear = (self.front + self.queSize) % self.capacity(); + var rear = (self.front + self.que_size) % self.capacity(); // 将 num 添加至队尾 self.nums[rear] = num; - self.queSize += 1; + self.que_size += 1; } // 出队 @@ -1596,7 +1596,7 @@ comments: true var num = self.peek(); // 队首指针向后移动一位,若越过尾部则返回到数组头部 self.front = (self.front + 1) % self.capacity(); - self.queSize -= 1; + self.que_size -= 1; return num; }