📜  C++标准模板库中的无序集(1)

📅  最后修改于: 2023-12-03 15:14:04.397000             🧑  作者: Mango

C++标准模板库中的无序集

无序集是C++标准模板库中的一个容器,也被称为哈希表或散列表。它可以快速插入、查询和删除数据,不同于有序集合,它不保持元素之间的任何特定关系。在无序集中,元素的存储位置在内部是无序的,但它们可以用哈希函数的输出映射到特定位置。通常,哈希函数将一个给定值映射到一个整数。

无序集的语法

C++标准模板库中的无序集定义如下:

std::unordered_set<Key,Hash,KeyEqual,Allocator>
  • Key:存储在无序集中的值的类型。
  • Hash:哈希函数的类型,用于将元素映射到特定位置。
  • KeyEqual:用于比较两个键是否相等的二元函数对象类型。如果两个键相等,则它们被视为一个键。
  • Allocator:定义内存分配策略的类型。

以下是使用无序集存储整数的示例:

#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> set = { 5, 2, 1, 8 };
    set.insert(3);
    for (auto i : set) {
        std::cout << i << " ";
    }
    return 0;
}

输出:

2 1 3 5 8
哈希函数

无序集使用哈希函数将元素映射到特定位置。C++标准库提供了一些内置哈希函数,如std::hash,用于将int类型的元素哈希。如果要使用自定义类型的元素,必须提供一个自定义哈希函数。

以下是使用自定义哈希函数的无序集示例:

#include <iostream>
#include <unordered_set>
#include <string>

struct Person {
    std::string name;
    int age;
};

struct PersonHasher {
    std::size_t operator()(const Person& p) const {
        std::size_t h1 = std::hash<std::string>{}(p.name);
        std::size_t h2 = std::hash<int>{}(p.age);
        return h1 ^ (h2 << 1);
    }
};

struct PersonEqual {
    bool operator()(const Person& lhs, const Person& rhs) const {
        return lhs.name == rhs.name && lhs.age == rhs.age;
    }
};

int main() {
    std::unordered_set<Person, PersonHasher, PersonEqual> set = { {"Alice", 20}, {"Bob", 25}, {"Charlie", 30} };
    set.insert({"Alice", 20});
    for (auto i : set) {
        std::cout << i.name << " " << i.age << std::endl;
    }
    return 0;
}

输出:

Charlie 30
Bob 25
Alice 20
性能

无序集的性能很快,大部分操作都需要常数级别的时间复杂度。然而,它的元素没有任何特殊的顺序,因此不能用下标运算符[]访问元素。

另外,无序集的占用内存较大,因为它必须维护一个哈希表以便放置元素。由于哈希表涉及到调整大小、重建等操作,因此它的性能可能波动很大,具体取决于元素的数量和哈希函数的质量。

总结

无序集是C++标准模板库中的一个重要数据结构,它可以快速插入、查询和删除数据,适用于大部分需要无序集合的应用场合。它的使用非常方便,只需提供元素的类型、哈希函数和键比较函数等信息即可。需要注意的是,它的内存占用较大,而且在不恰当的情况下可能导致性能下降。