哈希表!unordered_set和unordered_map

105 阅读4分钟

在C++中,unordered_setunordered_map是两个非常重要的关联容器,它们为开发者提供了基于哈希表的快速查找和插入操作。对于初学者来说,理解这两个容器的概念和基本特性,以及它们的使用场景,是非常有必要的。以下是对unordered_setunordered_map的个人理解介绍。

[来个例题](禁着点方案数 - MarsCode)

小U有一个长度为nn的数组,这个数组的元素被定义为“禁着点”。她现在希望你找出有多少对正整数 xx 和 yy,满足 x+y=sx+y=s 且 xx 和 yy 都不在禁着点的数组中。注意,(x,y)(x,y) 和 (y,x)(y,x) 被视为不同的正整数对。

这道题很明显就是枚举,然后查找枚举元素是否在禁用数组里面。遍历数组的话时间复杂会很高,因此可以用哈希表unordered_set来帮助我们储存数组,用其复杂度为O(1)来快速排查是否在数组里面。

int solution(int n, vector<int>& a, int s) {
    unordered_set<int> forbidden(a.begin(), a.end());
    int count = 0;
    for (int x = 1; x <=s/2; ++x) {
        int y = s - x;
        auto it1=forbidden.find(x);
        auto it2=forbidden.find(y);
        if ( it1==forbidden.end()&&it2==forbidden.end() ) {
            if(x==y)
            count++;
           else
            count+=2;
        }
    }
    return count;
}

unordered_set

unordered_set是一个无序集合,它包含唯一的元素,即集合中的每个元素都是唯一的,没有重复。与set不同,unordered_set不保证元素的排序,但通常提供了更快的插入和查找操作,因为它基于哈希表实现。

unordered_set中,元素的值同时也是唯一地标识它的键。这意味着,你不能通过值来访问元素,而只能通过键(在这里,键和值是相同的)来访问。由于unordered_set不保证元素的排序,因此它不适合需要元素有序的场景。

unordered_set的基本操作包括插入、查找、删除等。插入操作会向集合中添加一个新元素,如果元素已经存在,则插入操作不会改变集合。查找操作会检查一个元素是否在集合中,如果存在,则返回该元素的迭代器,否则返回集合的尾迭代器。删除操作会从集合中移除一个元素。

常用插入:set.insert(1);

unordered_set还提供了一个重要的成员函数count,它返回集合中某个元素的个数。对于unordered_set来说,这个函数的返回值只能是0或1,因为集合中的元素是唯一的。

unordered_map

unordered_map是一个无序关联数组(或哈希表),它存储键值对,并且每个键都是唯一的。与map不同,unordered_map不保证元素的排序,但通常提供了更快的插入、删除和查找操作。

unordered_map中,键值用于唯一地标识元素,而映射值是一个对象,其内容与此键关联。键和映射值的类型可能不同。例如,你可以有一个unordered_map<int, string>,其中键是整数,值是字符串。

unordered_map的基本操作与unordered_set类似,包括插入、查找、删除等。插入操作会向映射中添加一个新的键值对,如果键已经存在,则新的值会替换旧的值。查找操作会检查一个键是否在映射中,如果存在,则返回该键对应的值的迭代器,否则返回映射的尾迭代器。删除操作会从映射中移除一个键值对。

常用插入:myMap.insert({2, "two"});

unordered_map还提供了一个重要的成员函数operator[],它允许使用键作为参数直接访问对应的值。这个操作符在键不存在时会插入一个新的键值对,其中值为默认构造的值。因此,在使用这个操作符时需要小心,以避免不必要的插入操作。

使用场景

  • unordered_set适用于只关心元素是否存在的场景,不需要存储任何附加数据。例如,你可以使用unordered_set来检查一个元素是否已经被添加到集合中。
  • unordered_map适用于需要通过键来查找值的场景,常用于键值对的映射存储,如字典。例如,你可以使用unordered_map来存储学生的学号和姓名,以便通过学号快速查找学生的姓名。

查找是否存在元素

哈希表最重要的一个点就是可以快速查找是否存在查找元素,因此我们可以用find来快速寻找。 auto it=set.find(x) 这里it是一个迭代器,指代查找元素的,如果没有查找的元素,那么就是it==set.end(); 如果用的是unordered_map,那么it->first便代表查找元素,也就是键,而it->second则代表以查找元素为键的值。

总的来说,unordered_setunordered_map是C++中非常有用的两个关联容器,它们提供了基于哈希表的快速查找和插入操作。理解这两个容器的概念和基本特性是非常重要的.