mirror of
https://github.com/RustyCab/LearnRustEasy.git
synced 2026-02-08 04:45:07 +08:00
add chapter_3_15
This commit is contained in:
@@ -13,6 +13,14 @@
|
||||
- [所有权介绍](./chapter_3/chapter_3_7_1.md)
|
||||
- [引用与借用](./chapter_3/chapter_3_7_2.md)
|
||||
- [Slice类型](./chapter_3/chapter_3_7_3.md)
|
||||
- [3.15 常见Collections](./chapter_3/chapter_3_15.md)
|
||||
- [3.15.1 Vector](./chapter_3/chapter_3_15_1.md)
|
||||
- [3.15.2 String](./chapter_3/chapter_3_15_2.md)
|
||||
- [3.15.3 HashMap](./chapter_3/chapter_3_15_3.md)
|
||||
- [3.15.4 HashSet](./chapter_3/chapter_3_15_4.md)
|
||||
- [3.15.5 LinkedList](./chapter_3/chapter_3_15_5.md)
|
||||
- [3.15.6 BTreeMap](./chapter_3/chapter_3_15_6.md)
|
||||
- [3.15.7 BTreeSet](./chapter_3/chapter_3_15_7.md)
|
||||
- [3.20 Rust并发编程](./chapter_3/chapter_3_20.md)
|
||||
- [3.21 unsafe编程](./chapter_3/chapter_3_21.md)
|
||||
- [Rust使用技巧]()
|
||||
|
||||
9
src/chapter_3/chapter_3_15.md
Normal file
9
src/chapter_3/chapter_3_15.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 3.15 常见Collections
|
||||
|
||||
- [3.15.1 Vector(向量)](./chapter_3_15_1.md)
|
||||
- [3.15.2 String(字符串)](./chapter_3_15_2.md)
|
||||
- [3.15.3 HashMap(哈希映射)](./chapter_3_15_3.md)
|
||||
- [3.15.4 HashSet(哈希集合)](./chapter_3_15_4.md)
|
||||
- [3.15.5 LinkedList(链表)](./chapter_3_15_5.md)
|
||||
- [3.15.6 BTreeMap(B 树映射)](./chapter_3_15_6.md)
|
||||
- [3.15.7 BTreeSet(B 树集合)](./chapter_3_15_7.md)
|
||||
69
src/chapter_3/chapter_3_15_1.md
Normal file
69
src/chapter_3/chapter_3_15_1.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# 3.15.1 Vector(向量)
|
||||
|
||||
Rust 中的 Vector(向量)是一个动态的、可增长的数组,它可以存储一系列相同类型的元素。向量在连续的内存空间中存储元素,这使得访问和修改元素非常快。以下是有关 Rust 向量的一些详细信息:
|
||||
|
||||
## 1. 创建 Vector:
|
||||
|
||||
可以使用 Vec<T> 类型创建一个向量,其中 T 是存储在向量中的元素的类型。要创建一个新的空向量,可以使用 Vec::new() 方法。
|
||||
|
||||
```rust
|
||||
let mut vec = Vec::new();
|
||||
```
|
||||
|
||||
或者,可以使用宏 vec![] 初始化一个包含初始值的向量:
|
||||
|
||||
```rust
|
||||
let vec = vec![1, 2, 3, 4, 5];
|
||||
```
|
||||
|
||||
## 2. 添加元素:
|
||||
|
||||
可以使用 push() 方法向向量的末尾添加一个元素。
|
||||
```rust
|
||||
vec.push(6);
|
||||
```
|
||||
|
||||
## 3.访问元素:
|
||||
|
||||
可以通过索引访问向量中的元素,类似于数组。请注意,尝试访问无效索引可能导致运行时错误。
|
||||
|
||||
```rust
|
||||
let first = vec[0]; // 访问向量中的第一个元素
|
||||
```
|
||||
|
||||
或者,可以使用 get() 方法安全地访问元素,它返回一个 Option 类型。如果指定的索引有效,则返回 Some(element),否则返回 None。
|
||||
|
||||
```rust
|
||||
let first = vec.get(0); // 返回 Option<&T>
|
||||
```
|
||||
|
||||
## 4. 遍历元素:
|
||||
|
||||
可以使用 for 循环遍历向量中的所有元素。
|
||||
|
||||
```rust
|
||||
for element in &vec {
|
||||
println!("Element: {}", element);
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 删除元素:
|
||||
|
||||
可以使用 remove() 方法删除向量中指定索引处的元素。此操作将删除元素并将后续元素向前移动。
|
||||
|
||||
```rust
|
||||
vec.remove(0); // 删除向量中的第一个元素
|
||||
```
|
||||
|
||||
## 6. Vector 的容量和长度:
|
||||
|
||||
向量的长度是其中的元素数量,而容量是为这些元素分配的内存空间。向量会根据需要自动增长,但当长度超过容量时,它需要重新分配内存并复制元素到新内存区域。可以使用 len() 获取向量的长度,使用 capacity() 获取容量,还可以使用 shrink_to_fit() 方法减小容量以匹配当前长度。
|
||||
|
||||
## 7. 切片:
|
||||
|
||||
切片是对向量一部分元素的引用,可以用作轻量级的视图。要创建切片,可以使用范围语法:
|
||||
```rust
|
||||
let slice = &vec[1..4]; // 创建一个包含索引 1 到 3(包括 1,不包括 4)的元素的切片
|
||||
```
|
||||
|
||||
向量是 Rust 中使用非常广泛的集合类型,因为它提供了灵活性、性能和安全性。
|
||||
78
src/chapter_3/chapter_3_15_2.md
Normal file
78
src/chapter_3/chapter_3_15_2.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# 3.14.2 String(字符串)
|
||||
|
||||
Rust 中的 String(字符串)是一个可增长的、UTF-8 编码的字符串类型。它可以存储和处理文本数据。这里是关于 Rust 字符串的一些详细信息:
|
||||
|
||||
## 1. 创建 String:
|
||||
|
||||
可以使用 String::new() 创建一个新的空字符串,或者使用 String::from() 从字符串字面量创建字符串。
|
||||
```rust
|
||||
let mut s = String::new();
|
||||
let s = String::from("hello");
|
||||
```
|
||||
还可以使用 to_string() 方法将基本类型转换为字符串。
|
||||
```rust
|
||||
let num = 42;
|
||||
let s = num.to_string();
|
||||
```
|
||||
## 2. 字符串长度:
|
||||
|
||||
字符串的长度是其 UTF-8 编码的字节的数量,而不是 Unicode 字符的数量。可以使用 len() 方法获取字符串的长度。
|
||||
```rust
|
||||
let len = s.len();
|
||||
```
|
||||
|
||||
## 3. 字符串拼接:
|
||||
|
||||
有多种方法可以将字符串拼接在一起。例如,可以使用 + 运算符或 format! 宏。
|
||||
```rust
|
||||
let s1 = String::from("hello");
|
||||
let s2 = String::from("world");
|
||||
let s3 = s1 + " " + &s2;
|
||||
```
|
||||
或者使用 push_str() 方法将字符串附加到现有字符串。
|
||||
```rust
|
||||
let mut s = String::from("hello");
|
||||
s.push_str(" world");
|
||||
```
|
||||
## 4. 访问字符:
|
||||
|
||||
由于 Rust 字符串是 UTF-8 编码的,不能直接使用索引访问单个字符。但是,可以使用迭代器遍历字符串中的字符。
|
||||
```rust
|
||||
for c in s.chars() {
|
||||
println!("{}", c);
|
||||
}
|
||||
```
|
||||
|
||||
还可以使用 bytes() 方法遍历字节,或者使用 char_indices() 方法获取字符及其对应的字节索引。
|
||||
|
||||
## 5.字符串切片:
|
||||
|
||||
可以使用范围语法创建字符串的切片,它表示原始字符串中一部分的引用。需要确保范围边界位于有效的 UTF-8 字符边界上,否则将导致运行时错误。
|
||||
```rust
|
||||
let s = String::from("hello");
|
||||
let slice = &s[0..4]; // 获取字符串前 4 个字节的切片
|
||||
```
|
||||
|
||||
## 6. 修改字符串:
|
||||
|
||||
可以使用 push() 方法将一个字符添加到字符串的末尾,或者使用 insert()
|
||||
方法将字符插入指定的字节位置。
|
||||
|
||||
```rust
|
||||
let mut s = String::from("hello");
|
||||
s.push('!');
|
||||
s.insert(5, ',');
|
||||
```
|
||||
|
||||
注意,字符串插入操作可能需要 O(n) 时间,其中 n 是插入位置之后的字节数。
|
||||
|
||||
## 7. 删除字符串中的字符:
|
||||
|
||||
可以使用 pop() 方法删除并返回字符串末尾的字符,或者使用 remove() 方法删除并返回指定字节位置处的字符。
|
||||
```rust
|
||||
let mut s = String::from("hello");
|
||||
s.pop();
|
||||
s.remove(0);
|
||||
```
|
||||
|
||||
Rust 的字符串处理非常关注编码安全性和性能,因此,与其他编程语言相比,某些操作可能有所不同。然而,这使得 Rust 能够提供安全、高效的字符串操作。
|
||||
102
src/chapter_3/chapter_3_15_3.md
Normal file
102
src/chapter_3/chapter_3_15_3.md
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
# 3.15.3 HashMap(哈希映射)
|
||||
|
||||
Rust 中的 HashMap(哈希映射)是一个基于键值对的无序集合,它提供了高效的查找、插入和删除操作。HashMap 使用哈希函数将键映射到相应的存储桶,这使得大部分操作具有 O(1) 的平均时间复杂度。以下是有关 Rust HashMap 的一些详细信息:
|
||||
|
||||
## 1. 创建 HashMap:
|
||||
|
||||
要创建一个新的空 HashMap,可以使用 HashMap::new() 方法。需要导入 std::collections::HashMap 模块以使用 HashMap。
|
||||
```rust
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut map = HashMap::new();
|
||||
```
|
||||
|
||||
## 2. 插入键值对:
|
||||
|
||||
可以使用 insert() 方法向 HashMap 中添加键值对。如果使用相同的键插入新值,旧值将被替换。
|
||||
```rust
|
||||
map.insert("one", 1);
|
||||
map.insert("two", 2);
|
||||
```
|
||||
|
||||
## 3. 访问值:
|
||||
|
||||
可以使用 get() 方法根据键查找值。此方法返回一个 Option<&V> 类型,如果找到键,则返回 Some(&value),否则返回 None。
|
||||
```rust
|
||||
let value = map.get("one"); // 返回 Option<&V>
|
||||
```
|
||||
|
||||
还可以使用 get_mut() 方法获取可变引用。
|
||||
|
||||
## 4. 遍历键值对:
|
||||
|
||||
可以使用 for 循环遍历 HashMap 中的所有键值对。
|
||||
```rust
|
||||
for (key, value) in &map {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
```
|
||||
## 5. 删除键值对:
|
||||
|
||||
可以使用 remove() 方法根据键删除键值对。此方法返回一个 Option<V> 类型,如果找到并删除了键值对,则返回 Some(value),否则返回 None。
|
||||
```rust
|
||||
map.remove("one"); // 删除键为 "one" 的键值对
|
||||
```
|
||||
|
||||
## 6. 检查键是否存在:
|
||||
|
||||
可以使用 contains_key() 方法检查 HashMap 中是否存在指定的键。
|
||||
```rust
|
||||
let has_key = map.contains_key("one"); // 返回布尔值
|
||||
```
|
||||
|
||||
## 7. 更新值:
|
||||
|
||||
可以使用 entry() 方法与 or_insert() 方法结合,更新 HashMap 中的值或插入新值。
|
||||
```rust
|
||||
*map.entry("three").or_insert(3) += 1;
|
||||
```
|
||||
|
||||
## 8. HashMap 的容量和长度:
|
||||
|
||||
可以使用 len() 方法获取 HashMap 中的键值对数量,使用 capacity() 方法获取容量。还可以使用 shrink_to_fit() 方法减小容量以匹配当前长度。
|
||||
|
||||
## 9. 默认哈希器:
|
||||
|
||||
Rust 的 HashMap 默认使用一个加密安全的哈希函数(SipHash),它在防止哈希碰撞攻击方面表现良好,但可能不如其他哈希函数快。可以通过为 HashMap 类型提供自定义的哈希器来改变默认行为。
|
||||
|
||||
```rust
|
||||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use twox_hash::XxHash64;
|
||||
|
||||
type FastHashMap<K, V> = HashMap<K, V, BuildHasherDefault<XxHash64>>;
|
||||
|
||||
let mut map: FastHashMap<&str, i32> = FastHashMap::default();
|
||||
map.insert("one", 1);
|
||||
map.insert("two", 2);
|
||||
```
|
||||
|
||||
在这个例子中,我们使用了 twox_hash 库中的 XxHash64 哈希函数,它通常比默认的 SipHash 更快。请注意,使用自定义哈希函数可能会降低安全性,因此要确保在明确了解潜在风险的情况下进行更改。
|
||||
|
||||
## 10. 合并两个 HashMap:
|
||||
|
||||
可以使用 extend() 方法将另一个 HashMap 的键值对添加到当前 HashMap 中。如果存在重复的键,目标 HashMap 中的值将被源 HashMap 中的值覆盖。
|
||||
|
||||
```rust
|
||||
let mut map1 = HashMap::new();
|
||||
map1.insert("one", 1);
|
||||
map1.insert("two", 2);
|
||||
|
||||
let mut map2 = HashMap::new();
|
||||
map2.insert("two", 22);
|
||||
map2.insert("three", 3);
|
||||
|
||||
map1.extend(map2); // 将 map2 中的键值对添加到 map1
|
||||
```
|
||||
|
||||
这样,map1 将包含键值对 "one" -> 1, "two" -> 22 和 "three" -> 3。
|
||||
|
||||
总之,Rust 中的 HashMap 是一个功能丰富且性能优越的键值对集合,非常适合在需要快速查找和修改操作的场景中使用。
|
||||
103
src/chapter_3/chapter_3_15_4.md
Normal file
103
src/chapter_3/chapter_3_15_4.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# 3.15.4 HashSet(哈希集合)
|
||||
|
||||
Rust 中的 HashSet(哈希集合)是一种无序的、不含重复元素的集合。它使用哈希函数将元素映射到相应的存储桶,这使得大部分操作具有 O(1) 的平均时间复杂度。以下是有关 Rust HashSet 的一些详细信息:
|
||||
|
||||
## 1. 创建 HashSet:
|
||||
|
||||
要创建一个新的空 HashSet,可以使用 HashSet::new() 方法。需要导入 std::collections::HashSet 模块以使用 HashSet。
|
||||
```rust
|
||||
use std::collections::HashSet;
|
||||
|
||||
let mut set = HashSet::new();
|
||||
```
|
||||
|
||||
## 2. 添加元素:
|
||||
|
||||
可以使用 insert() 方法向 HashSet 中添加元素。如果元素已存在,则此方法将返回 false,否则返回 true。
|
||||
|
||||
```rust
|
||||
set.insert(1);
|
||||
set.insert(2);
|
||||
set.insert(3);
|
||||
```
|
||||
|
||||
## 3. 检查元素是否存在:
|
||||
|
||||
可以使用 contains() 方法检查 HashSet 中是否存在指定的元素。
|
||||
```rust
|
||||
let contains = set.contains(&1); // 返回布尔值
|
||||
```
|
||||
|
||||
## 4. 删除元素:
|
||||
|
||||
可以使用 remove() 方法删除 HashSet 中的元素。此方法返回一个 bool 类型,如果找到并删除了元素,则返回 true,否则返回 false。
|
||||
```rust
|
||||
set.remove(&1); // 删除元素 1
|
||||
```
|
||||
|
||||
## 5. 遍历元素:
|
||||
|
||||
可以使用 for 循环遍历 HashSet 中的所有元素。
|
||||
```rust
|
||||
for element in &set {
|
||||
println!("{}", element);
|
||||
}
|
||||
```
|
||||
|
||||
## 6. HashSet 的长度:
|
||||
|
||||
可以使用 len() 方法获取 HashSet 中的元素数量。还可以使用 is_empty() 方法检查 HashSet 是否为空。
|
||||
|
||||
## 7. 集合操作:
|
||||
|
||||
HashSet 支持一些基本的集合操作,如并集、交集、差集和对称差集。
|
||||
|
||||
- 并集(union):返回一个新的 HashSet,包含两个集合中的所有元素。
|
||||
|
||||
```rust
|
||||
let set1: HashSet<_> = [1, 2, 3].iter().cloned().collect();
|
||||
let set2: HashSet<_> = [3, 4, 5].iter().cloned().collect();
|
||||
let union: HashSet<_> = set1.union(&set2).cloned().collect();
|
||||
```
|
||||
|
||||
- 交集(intersection):返回一个新的 HashSet,包含两个集合中共有的元素。
|
||||
|
||||
```rust
|
||||
let intersection: HashSet<_> = set1.intersection(&set2).cloned().collect();
|
||||
```
|
||||
|
||||
- 差集(difference):返回一个新的 HashSet,包含第一个集合中存在但第二个集合中不存在的元素。
|
||||
```rust
|
||||
let difference: HashSet<_> = set1.difference(&set2).cloned().collect();
|
||||
```
|
||||
- 对称差集(symmetric_difference):返回一个新的 HashSet,包含两个集合中唯一的元素(也就是只存在于一个集合中的元素)。
|
||||
```rust
|
||||
let symmetric_difference: HashSet<_> = set1.symmetric_difference(&set2).cloned().collect();
|
||||
```
|
||||
|
||||
## 8. 清空 HashSet:
|
||||
|
||||
可以使用 clear() 方法删除 HashSet 中的所有元素。
|
||||
|
||||
```rust
|
||||
set.clear(); // 清空 HashSet
|
||||
```
|
||||
|
||||
总的来说,Rust 中的 HashSet提供了一种高效且易于使用的无序集合实现,适用于需要快速查找、添加和删除操作的场景。由于 HashSet 的底层实现基于哈希表,它能够在大部分情况下为这些操作提供 O(1) 的平均时间复杂度。
|
||||
|
||||
与 HashMap 类似,Rust 的 HashSet 默认使用一个加密安全的哈希函数(SipHash),以防止哈希碰撞攻击。如果需要更高的性能,可以考虑使用自定义哈希器,但要确保在明确了解潜在风险的情况下进行更改。这是一个使用自定义哈希器的例子
|
||||
:
|
||||
|
||||
```rust
|
||||
use std::collections::HashSet;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use twox_hash::XxHash64;
|
||||
|
||||
type FastHashSet<T> = HashSet<T, BuildHasherDefault<XxHash64>>;
|
||||
|
||||
let mut set: FastHashSet<i32> = FastHashSet::default();
|
||||
set.insert(1);
|
||||
set.insert(2);
|
||||
```
|
||||
|
||||
在这个例子中,我们使用了 twox_hash 库中的 XxHash64 哈希函数,它通常比默认的 SipHash 更快。
|
||||
80
src/chapter_3/chapter_3_15_5.md
Normal file
80
src/chapter_3/chapter_3_15_5.md
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
# 3.15.5 LinkedList(链表)
|
||||
|
||||
Rust 中的 LinkedList(链表)是一种线性数据结构,它由一系列相互连接的节点组成。每个节点都包含一个元素和指向前一个节点和后一个节点的指针。这是有关 Rust LinkedList 的一些详细信息:
|
||||
|
||||
## 1. 创建 LinkedList:
|
||||
|
||||
要创建一个新的空 LinkedList,可以使用 LinkedList::new() 方法。需要导入 std::collections::LinkedList 模块以使用 LinkedList。
|
||||
```rust
|
||||
use std::collections::LinkedList;
|
||||
|
||||
let mut list = LinkedList::new();
|
||||
```
|
||||
|
||||
## 2. 添加元素:
|
||||
|
||||
可以使用 push_front() 和 push_back() 方法将元素添加到链表的开头和结尾。
|
||||
```rust
|
||||
list.push_front(1);
|
||||
list.push_back(2);
|
||||
```
|
||||
|
||||
## 3. 访问元素:
|
||||
|
||||
可以使用 front() 和 back() 方法分别访问链表的第一个和最后一个元素。这些方法返回一个 Option<&T> 类型,如果链表不为空,则返回 Some(&element),否则返回 None。
|
||||
|
||||
```rust
|
||||
let first_element = list.front(); // 返回 Option<&T>
|
||||
let last_element = list.back(); // 返回 Option<&T>
|
||||
```
|
||||
|
||||
还可以使用 front_mut() 和 back_mut() 方法获取可变引用。
|
||||
|
||||
## 4. 删除元素:
|
||||
|
||||
可以使用 pop_front() 和 pop_back() 方法分别删除并返回链表的第一个和最后一个元素。这些方法返回一个 Option<T> 类型,如果链表不为空且成功删除元素,则返回 Some(element),否则返回 None。
|
||||
```rust
|
||||
list.pop_front(); // 删除并返回第一个元素
|
||||
list.pop_back(); // 删除并返回最后一个元素
|
||||
```
|
||||
|
||||
## 5. 遍历元素:
|
||||
|
||||
可以使用 iter() 方法遍历链表中的所有元素。iter_mut() 方法可用于遍历可变引用。
|
||||
```rust
|
||||
for element in list.iter() {
|
||||
println!("{}", element);
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 链表长度:
|
||||
|
||||
可以使用 len() 方法获取链表中的元素数量。还可以使用 is_empty() 方法检查链表是否为空。
|
||||
|
||||
## 7. 清空链表:
|
||||
|
||||
可以使用 clear() 方法删除链表中的所有元素。
|
||||
|
||||
```rust
|
||||
list.clear(); // 清空链表
|
||||
```
|
||||
|
||||
## 8. 分割链表:
|
||||
|
||||
可以使用 split_off() 方法在指定索引处分割链表。此操作会将链表分成两个链表,前一个链表包含指定索引之前的元素,后一个链表包含指定索引及之后的元素。
|
||||
|
||||
```rust
|
||||
let mut list1 = LinkedList::new();
|
||||
list1.push_back(1);
|
||||
list1.push_back(2);
|
||||
list1.push_back(3);
|
||||
|
||||
let list2 = list1.split_off(1);
|
||||
```
|
||||
|
||||
这样,list1 将包含元素 1,而 list2 将包含元素 2 和 3。
|
||||
|
||||
总之,Rust 中的 LinkedList 提供了一种基于节点的线性数据结构,它适用于需要快速插入和删除操作的场景。然而,对于许多其他用途,如随机访问和查找操作,链表通常比数组或向量(Vector)等基于连续内存的数据结构性能差。这是因为链表的元素在内存中是分散存储的,这会导致较差的缓存局部性(cache locality)。而连续内存数据结构在许多情况下可以更有效地利用 CPU 缓存,从而提高性能。
|
||||
|
||||
当考虑使用链表时,务必评估其适用性,并与其他数据结构(如 Vector)进行比较。在某些情况下,链表可能是一个很好的选择,特别是当插入和删除操作的性能比访问和查找操作更重要时。然而,在许多场景中,使用基于连续内存的数据结构会带来更好的性能和更简单的代码。
|
||||
71
src/chapter_3/chapter_3_15_6.md
Normal file
71
src/chapter_3/chapter_3_15_6.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# 3.15.6 BTreeMap(B 树映射)
|
||||
|
||||
Rust 中的 BTreeMap(B 树映射)是一种自平衡的有序映射数据结构,它以 B 树的形式存储键值对。BTreeMap 具有对数级的时间复杂度,这使得它在需要维护键的顺序时非常有效。以下是有关 Rust BTreeMap 的一些详细信息:
|
||||
|
||||
## 1. 创建 BTreeMap:
|
||||
|
||||
要创建一个新的空 BTreeMap,可以使用 BTreeMap::new() 方法。需要导入 std::collections::BTreeMap 模块以使用 BTreeMap。
|
||||
|
||||
```rust
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
let mut map = BTreeMap::new();
|
||||
```
|
||||
|
||||
## 2. 添加元素:
|
||||
|
||||
可以使用 insert() 方法向 BTreeMap 中添加键值对。如果键已存在,则此方法将返回 Some(old_value),否则返回 None。
|
||||
```rust
|
||||
map.insert("one", 1);
|
||||
map.insert("two", 2);
|
||||
map.insert("three", 3);
|
||||
```
|
||||
|
||||
## 3. 访问元素:
|
||||
|
||||
可以使用 get() 方法根据键查找对应的值。此方法返回一个 Option<&V> 类型,如果找到键,则返回 Some(&value),否则返回 None。
|
||||
|
||||
```rust
|
||||
let value = map.get("one"); // 返回 Option<&V>
|
||||
```
|
||||
|
||||
还可以使用 get_mut() 方法获取可变引用。
|
||||
|
||||
## 4. 删除元素:
|
||||
|
||||
可以使用 remove() 方法删除 BTreeMap 中的键值对。此方法返回一个 Option<V> 类型,如果找到并删除了键值对,则返回 Some(value),否则返回 None。
|
||||
|
||||
```rust
|
||||
map.remove("one"); // 删除键为 "one" 的键值对
|
||||
```
|
||||
|
||||
## 5. 遍历元素:
|
||||
|
||||
可以使用 iter() 方法遍历 BTreeMap 中的所有键值对。遍历顺序按键的顺序进行。iter_mut() 方法可用于遍历可变引用。
|
||||
```rust
|
||||
for (key, value) in map.iter() {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
```
|
||||
|
||||
## 6. BTreeMap 的长度:
|
||||
|
||||
可以使用 len() 方法获取 BTreeMap 中的键值对数量。还可以使用 is_empty() 方法检查 BTreeMap 是否为空。
|
||||
|
||||
## 7. 最小和最大键:
|
||||
|
||||
可以使用 first_key_value() 和 last_key_value() 方法分别获取 BTreeMap 中具有最小和最大键的键值对。这些方法返回一个 Option<(&K, &V)> 类型,如果找到键值对,则返回 Some((&key, &value)),否则返回 None。
|
||||
|
||||
```rust
|
||||
let min_key_value = map.first_key_value(); // 返回 Option<(&K, &V)>
|
||||
let max_key_value = map.last_key_value(); // 返回 Option<(&K, &V)>
|
||||
```
|
||||
|
||||
## 8. 范围查询:
|
||||
|
||||
可以使用 range() 方法查询 BTreeMap 中某个范围内的键值对。例如,可以查询所有键大于等于 "one" 且小于等于 "three" 的键值对:
|
||||
```rust
|
||||
for (key, value) in map.range("one".."three") {
|
||||
println!("{}: {}", key, value);
|
||||
}
|
||||
```
|
||||
97
src/chapter_3/chapter_3_15_7.md
Normal file
97
src/chapter_3/chapter_3_15_7.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 3.15.7 BTreeSet(B 树集合)
|
||||
|
||||
Rust 中的 BTreeSet(B 树集合)是一种自平衡的有序集合数据结构,它以 B 树的形式存储元素。BTreeSet 具有对数级的时间复杂度,这使得它在需要维护元素顺序时非常有效。以下是有关 Rust BTreeSet 的一些详细信息:
|
||||
|
||||
## 1. 创建 BTreeSet:
|
||||
|
||||
要创建一个新的空 BTreeSet,可以使用 BTreeSet::new() 方法。需要导入 std::collections::BTreeSet 模块以使用 BTreeSet。
|
||||
```rust
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
let mut set = BTreeSet::new();
|
||||
```
|
||||
|
||||
## 2. 添加元素:
|
||||
|
||||
可以使用 insert() 方法向 BTreeSet 中添加元素。如果元素已存在,则此方法将返回 false,否则返回 true。
|
||||
```rust
|
||||
set.insert(1);
|
||||
set.insert(2);
|
||||
set.insert(3);
|
||||
```
|
||||
|
||||
## 3. 检查元素是否存在:
|
||||
|
||||
可以使用 contains() 方法检查 BTreeSet 中是否存在指定的元素。
|
||||
```rust
|
||||
let contains = set.contains(&1); // 返回布尔值
|
||||
```
|
||||
|
||||
## 4. 删除元素:
|
||||
|
||||
可以使用 remove() 方法删除 BTreeSet 中的元素。此方法返回一个 bool 类型,如果找到并删除了元素,则返回 true,否则返回 false。
|
||||
```rust
|
||||
set.remove(&1); // 删除元素 1
|
||||
```
|
||||
|
||||
## 5. 遍历元素:
|
||||
|
||||
可以使用 for 循环遍历 BTreeSet 中的所有元素。遍历顺序按元素的顺序进行。
|
||||
```rust
|
||||
for element in &set {
|
||||
println!("{}", element);
|
||||
}
|
||||
```
|
||||
|
||||
## 6. BTreeSet 的长度:
|
||||
|
||||
可以使用 len() 方法获取 BTreeSet 中的元素数量。还可以使用 is_empty() 方法检查 BTreeSet 是否为空。
|
||||
|
||||
## 7. 集合操作:
|
||||
|
||||
BTreeSet 支持一些基本的集合操作,如并集、交集、差集和对称差集。
|
||||
|
||||
- 并集(union):返回一个新的 BTreeSet,包含两个集合中的所有元素。
|
||||
```rust
|
||||
let set1: BTreeSet<_> = [1, 2, 3].iter().cloned().collect();
|
||||
let set2: BTreeSet<_> = [3, 4, 5].iter().cloned().collect();
|
||||
let union: BTreeSet<_> = set1.union(&set2).cloned().collect();
|
||||
```
|
||||
- 交集(intersection):返回一个新的 BTreeSet,包含两个集合中共有的元素。
|
||||
```rust
|
||||
let intersection: BTreeSet<_> = set1.intersection(&set2).cloned().collect();
|
||||
```
|
||||
- 差集(difference):返回一个新的 BTreeSet,包含第一个集合中存在但第二个集合中不存在的元素。
|
||||
```rust
|
||||
let difference: BTreeSet<_> = set1.difference(&set2).cloned().collect();
|
||||
```
|
||||
- 对称差集(symmetric_difference):返回一个新的 BTreeSet,包含两个集合中唯一的元素(也就是只存在于一个集合中的元素)
|
||||
```rust
|
||||
let symmetric_difference: BTreeSet<_> = set1.symmetric_difference(&set2).cloned().collect();
|
||||
```
|
||||
## 8. 最小和最大元素:
|
||||
|
||||
可以使用 first() 和 last() 方法分别获取 BTreeSet 中的最小和最大元素。这些方法返回一个 Option<&T> 类型,如果找到元素,则返回 Some(&element),否则返回 None。
|
||||
```rust
|
||||
let min_element = set.first(); // 返回 Option<&T>
|
||||
let max_element = set.last(); // 返回 Option<&T>
|
||||
```
|
||||
|
||||
## 9. 范围查询:
|
||||
|
||||
可以使用 range() 方法查询 BTreeSet 中某个范围内的元素。例如,可以查询所有大于等于 1 且小于等于 3 的元素:
|
||||
```rust
|
||||
for element in set.range(1..=3) {
|
||||
println!("{}", element);
|
||||
}
|
||||
```
|
||||
|
||||
## 10. 清空 BTreeSet:
|
||||
|
||||
可以使用 clear() 方法删除 BTreeSet 中的所有元素。
|
||||
|
||||
```rust
|
||||
set.clear(); // 清空 BTreeSet
|
||||
```
|
||||
|
||||
总之,Rust 中的 BTreeSet 提供了一种有序集合数据结构,适用于需要维护元素顺序以及执行集合操作的场景。与 BTreeMap 类似,BTreeSet 具有对数级的时间复杂度,这使得它在需要维护元素顺序时非常有效。然而,在需要快速查找、添加和删除操作的场景中,使用基于哈希表的数据结构(如 HashSet)可能更适合。
|
||||
Reference in New Issue
Block a user