From 96aa22f1a49a3c7122a9e60c9e2c68cc865b2933 Mon Sep 17 00:00:00 2001 From: Davirain Date: Wed, 17 May 2023 20:34:44 +0800 Subject: [PATCH] add chapter_3_15 --- src/SUMMARY.md | 8 +++ src/chapter_3/chapter_3_15.md | 9 +++ src/chapter_3/chapter_3_15_1.md | 69 +++++++++++++++++++++ src/chapter_3/chapter_3_15_2.md | 78 ++++++++++++++++++++++++ src/chapter_3/chapter_3_15_3.md | 102 +++++++++++++++++++++++++++++++ src/chapter_3/chapter_3_15_4.md | 103 ++++++++++++++++++++++++++++++++ src/chapter_3/chapter_3_15_5.md | 80 +++++++++++++++++++++++++ src/chapter_3/chapter_3_15_6.md | 71 ++++++++++++++++++++++ src/chapter_3/chapter_3_15_7.md | 97 ++++++++++++++++++++++++++++++ 9 files changed, 617 insertions(+) create mode 100644 src/chapter_3/chapter_3_15.md create mode 100644 src/chapter_3/chapter_3_15_1.md create mode 100644 src/chapter_3/chapter_3_15_2.md create mode 100644 src/chapter_3/chapter_3_15_3.md create mode 100644 src/chapter_3/chapter_3_15_4.md create mode 100644 src/chapter_3/chapter_3_15_5.md create mode 100644 src/chapter_3/chapter_3_15_6.md create mode 100644 src/chapter_3/chapter_3_15_7.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1501332..0616af9 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -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使用技巧]() diff --git a/src/chapter_3/chapter_3_15.md b/src/chapter_3/chapter_3_15.md new file mode 100644 index 0000000..5c9ab6e --- /dev/null +++ b/src/chapter_3/chapter_3_15.md @@ -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) diff --git a/src/chapter_3/chapter_3_15_1.md b/src/chapter_3/chapter_3_15_1.md new file mode 100644 index 0000000..87ad5c3 --- /dev/null +++ b/src/chapter_3/chapter_3_15_1.md @@ -0,0 +1,69 @@ +# 3.15.1 Vector(向量) + +Rust 中的 Vector(向量)是一个动态的、可增长的数组,它可以存储一系列相同类型的元素。向量在连续的内存空间中存储元素,这使得访问和修改元素非常快。以下是有关 Rust 向量的一些详细信息: + +## 1. 创建 Vector: + +可以使用 Vec 类型创建一个向量,其中 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 中使用非常广泛的集合类型,因为它提供了灵活性、性能和安全性。 diff --git a/src/chapter_3/chapter_3_15_2.md b/src/chapter_3/chapter_3_15_2.md new file mode 100644 index 0000000..a5f6861 --- /dev/null +++ b/src/chapter_3/chapter_3_15_2.md @@ -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 能够提供安全、高效的字符串操作。 diff --git a/src/chapter_3/chapter_3_15_3.md b/src/chapter_3/chapter_3_15_3.md new file mode 100644 index 0000000..0f42035 --- /dev/null +++ b/src/chapter_3/chapter_3_15_3.md @@ -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 类型,如果找到并删除了键值对,则返回 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 = HashMap>; + +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 是一个功能丰富且性能优越的键值对集合,非常适合在需要快速查找和修改操作的场景中使用。 diff --git a/src/chapter_3/chapter_3_15_4.md b/src/chapter_3/chapter_3_15_4.md new file mode 100644 index 0000000..7ba6cc7 --- /dev/null +++ b/src/chapter_3/chapter_3_15_4.md @@ -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 = HashSet>; + +let mut set: FastHashSet = FastHashSet::default(); +set.insert(1); +set.insert(2); +``` + +在这个例子中,我们使用了 twox_hash 库中的 XxHash64 哈希函数,它通常比默认的 SipHash 更快。 diff --git a/src/chapter_3/chapter_3_15_5.md b/src/chapter_3/chapter_3_15_5.md new file mode 100644 index 0000000..492ac50 --- /dev/null +++ b/src/chapter_3/chapter_3_15_5.md @@ -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 类型,如果链表不为空且成功删除元素,则返回 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)进行比较。在某些情况下,链表可能是一个很好的选择,特别是当插入和删除操作的性能比访问和查找操作更重要时。然而,在许多场景中,使用基于连续内存的数据结构会带来更好的性能和更简单的代码。 diff --git a/src/chapter_3/chapter_3_15_6.md b/src/chapter_3/chapter_3_15_6.md new file mode 100644 index 0000000..cb99901 --- /dev/null +++ b/src/chapter_3/chapter_3_15_6.md @@ -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 类型,如果找到并删除了键值对,则返回 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); +} +``` diff --git a/src/chapter_3/chapter_3_15_7.md b/src/chapter_3/chapter_3_15_7.md new file mode 100644 index 0000000..88f180f --- /dev/null +++ b/src/chapter_3/chapter_3_15_7.md @@ -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)可能更适合。