Loading... ### C++深度探索:`unordered_set` 与 `unordered_map` 的封装 在C++标准库中,`unordered_set` 和 `unordered_map` 是两个非常重要的容器类,提供了基于哈希表的集合和映射功能。相比于传统的 `set`和 `map`,它们具有更快的查找、插入和删除操作,特别是在处理大量数据时表现尤为突出。本文将深入探讨如何封装和扩展 `unordered_set`与 `unordered_map`,以便更好地满足具体的应用需求。 #### 一、`unordered_set` 与 `unordered_map` 的基本使用 在探讨封装之前,先简要回顾一下这两个容器的基本用法。 ##### 1.1 `unordered_set` 基本用法 `unordered_set` 是一个不允许重复元素的集合,所有元素的顺序是由哈希函数决定的。以下是 `unordered_set`的基本用法: ```cpp #include <iostream> #include <unordered_set> int main() { std::unordered_set<int> mySet = {1, 2, 3, 4, 5}; // 插入元素 mySet.insert(6); // 查找元素 if (mySet.find(3) != mySet.end()) { std::cout << "3 exists in the set" << std::endl; } // 删除元素 mySet.erase(4); // 遍历元素 for (const int& elem : mySet) { std::cout << elem << " "; } std::cout << std::endl; return 0; } ``` **解释:** - `insert` 用于向集合中添加元素。 - `find` 返回一个迭代器,如果元素存在,迭代器指向该元素;否则指向 `end`。 - `erase` 用于从集合中删除元素。 ##### 1.2 `unordered_map` 基本用法 `unordered_map` 是一个基于哈希表的键值对映射容器,其中每个键是唯一的。以下是 `unordered_map`的基本用法: ```cpp #include <iostream> #include <unordered_map> int main() { std::unordered_map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}, {"cherry", 3}}; // 插入元素 myMap["date"] = 4; // 查找元素 if (myMap.find("banana") != myMap.end()) { std::cout << "banana exists with value: " << myMap["banana"] << std::endl; } // 删除元素 myMap.erase("apple"); // 遍历元素 for (const auto& pair : myMap) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; } ``` **解释:** - `myMap["date"] = 4` 直接插入或修改映射关系。 - `find` 查找键并返回相应的迭代器。 - `erase` 用于删除指定键及其对应的值。 #### 二、`unordered_set` 与 `unordered_map` 的封装 在实际开发中,可能需要对这两个容器进行封装,以便实现更多功能或满足特定的业务需求。以下将探讨如何进行封装。 ##### 2.1 封装 `unordered_set` 假设我们需要封装一个支持快速插入、删除,并能统计元素插入次数的集合,可以基于 `unordered_set`进行封装。 ```cpp #include <iostream> #include <unordered_set> #include <unordered_map> template <typename T> class CountingSet { private: std::unordered_set<T> set; std::unordered_map<T, int> countMap; public: void insert(const T& value) { set.insert(value); countMap[value]++; } void erase(const T& value) { set.erase(value); countMap.erase(value); } int count(const T& value) const { auto it = countMap.find(value); if (it != countMap.end()) { return it->second; } return 0; } bool contains(const T& value) const { return set.find(value) != set.end(); } void display() const { for (const auto& value : set) { std::cout << value << ": " << countMap.at(value) << std::endl; } } }; ``` **解释:** - `CountingSet` 封装了一个 `unordered_set`用于存储元素,同时用一个 `unordered_map`来记录每个元素的插入次数。 - `insert` 方法不仅将元素插入集合,还会更新该元素的计数。 - `count` 方法返回指定元素的插入次数。 ##### 2.2 封装 `unordered_map` 假设我们需要一个 `unordered_map`,它不仅可以存储键值对,还能跟踪访问次数,我们可以进行如下封装: ```cpp #include <iostream> #include <unordered_map> template <typename K, typename V> class TrackingMap { private: std::unordered_map<K, V> map; std::unordered_map<K, int> accessCount; public: void insert(const K& key, const V& value) { map[key] = value; } V& operator[](const K& key) { accessCount[key]++; return map[key]; } int getAccessCount(const K& key) const { auto it = accessCount.find(key); if (it != accessCount.end()) { return it->second; } return 0; } void display() const { for (const auto& pair : map) { std::cout << pair.first << ": " << pair.second << " (Accessed: " << accessCount.at(pair.first) << " times)" << std::endl; } } }; ``` **解释:** - `TrackingMap` 封装了一个 `unordered_map`,并使用另一个 `unordered_map`来跟踪每个键的访问次数。 - `operator[]` 重载用于访问值,并在访问时更新访问计数。 - `getAccessCount` 返回指定键的访问次数。 #### 三、应用场景分析 封装后的 `unordered_set`和 `unordered_map`适用于以下场景: 1. **统计分析**:需要在插入或访问元素时收集统计信息,如访问频率或插入次数。 2. **缓存机制**:在实现简单的缓存时,可以使用 `TrackingMap`记录数据的访问频率,便于实现LRU(最近最少使用)算法等。 3. **数据验证**:`CountingSet` 可以帮助在数据处理过程中确保元素唯一性,同时统计元素的重复次数。 #### 四、总结 通过本文的讨论,我们深入探讨了 `unordered_set`与 `unordered_map`的基础用法,并通过实际例子展示了如何对它们进行封装,以实现更丰富的功能。在实际开发中,根据具体需求对容器类进行扩展,可以极大地提升代码的灵活性和功能性。希望本文能够帮助你更好地理解和运用C++标准库中的这两个重要容器。 最后修改:2024 年 08 月 21 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏