unordered_set的理解与使用

本文详细介绍了C++ STL中的unordered_set容器,包括其基本概念、构造与赋值、迭代器使用、容量检查、元素插入与删除等功能,并探讨了查找、桶接口及哈希策略等方面的知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

unordered_set理解

unordered_set 是含有 Key 类型唯一对象集合的关联容器。搜索、插入和移除拥有平均常数时间复杂度。
在内部,元素并不以任何特别顺序排序,而是组织进桶中。元素被放进哪个桶完全依赖其值的哈希。这允许对单独元素的快速访问,因为哈希一旦确定,就准确指代元素被放入的桶。
不可修改容器元素(即使通过非 const 迭代器),因为修改可能更改元素的哈希,并破坏容器。

对外封装的函数

成员函数

成员函数功能
unordered_set( )构造空容器。
template< class InputIt > unordered_set( InputIt first, InputIt last)构造拥有范围 [first, last) 的内容的容器。
unordered_set( const unordered_set& other );复制构造函数。构造拥有 other 内容副本的容器,一同复制加载因子、谓词和哈希函数。
unordered_set( unordered_set&& other );移动构造函数。用移动语义构造拥有 other 内容的容器。
unordered_set& operator=( const unordered_set& other );复制赋值运算符。以 other 的副本替换内容。
unordered_set& operator=( unordered_set&& other );移动赋值运算符。用移动语义以 other 的内容替换内容(即从 other 移动 other 中的数据到此容器中)。之后 other 在合法但未指定的状态。
#include <iostream>
#include <unordered_set>

using namespace std;

int main()
{
    unordered_set<int> set1;//默认构造函数

    unordered_set<int> set2({ 3, 7 });//(列表构造函数)构造拥有范围 [first, last) 的内容的容器。

    unordered_set<int> set3(set2);//复制构造函数

    unordered_set<int> set4(move(set2));//移动构造函数

    unordered_set<int> set5 = set3;//复制构造函数

    unordered_set<int> set6 = move(set3);//移动构造函数



    return 0;
}

迭代器

迭代器功能
iterator begin() ;返回指向 unordered_set 首元素的迭代器。若 unordered_set 为空,则返回的迭代器将等于 end() 。
const_iterator cbegin() const ;返回指向 unordered_set 首元素的迭代器。若 unordered_set 为空,则返回的迭代器将等于 end() 。
iterator end() ;返回指向 unordered_set 末元素后一元素的迭代器。
const_iterator cend() const ;返回指向 unordered_set 末元素后一元素的迭代器。

在这里插入图片描述

#include <iostream>
#include <unordered_set>

using namespace std;

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });

    auto it = set1.begin();

    while (it != set1.end())
    {
        cout << *it << "  ";
        it++;
    }
    cout << endl;

    return 0;
}

在这里插入图片描述

容量

容量功能
bool empty() const;检查容器是否无元素,即是否 begin() == end() 。若容器为空则为 true ,否则为 false
size_type size() const ;返回容器中的元素数,即 std::distance(begin(), end()) 。
size_type max_size() const ;返回根据系统或库实现限制的容器可保有的元素最大数量
#include <iostream>
#include <unordered_set>

using namespace std;

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });

    cout << "set1.empty():" << set1.empty() << endl;
    cout << "set1.size():" << set1.size() << endl;
    cout << "set1.max_size():" << set1.max_size() << endl;

    return 0;
}

在这里插入图片描述

修改器

修改器功能
void clear() ;从容器擦除所有元素。此调用后 size() 返回零。
std::pair<iterator,bool> insert( const value_type& value )若容器尚未含有带等价关键的元素,则插入元素到容器中。 插入 value 。
iterator insert( const_iterator hint, const value_type& value );插入 value ,以 hint 为应当开始搜索的位置的非强制建议。
template< class InputIt >void insert( InputIt first, InputIt last );插入来自范围 [first, last) 的元素。
void insert( std::initializer_list<value_type> ilist );插入来自 initializer_list ilist 的元素。
iterator erase( iterator pos );移除位于 pos 的元素。
iterator erase( const_iterator first, const_iterator last );移除范围 [first; last) 中的元素
size_type erase( const key_type& key );移除键等价于 key 的元素(如果存在一个)。
void swap( unordered_set& other );将内容与 other 的交换。

insert,clear,emplace

#include <iostream>
#include <unordered_set>

using namespace std;


void Print(unordered_set<int>& set)
{
    auto it = set.begin();

    while (it != set.end())
    {
        cout << *it << "  ";
        it++;
    }
    cout << endl;
}

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });
    

    set1.insert(set1.begin(), 11);//插入 value ,以 hint 为应当开始搜索的位置的非强制建议。
    Print(set1);

    auto it1 = set1.insert(100);//插入 value 
    cout << "*it1.first:" << *it1.first << "    it1.second:" << it1.second << endl;
    Print(set1);

    set1.clear();//从容器擦除所有元素。
    Print(set1);

    set1.insert({ 13,17 });//插入来自范围 [first, last) 的元素。
    Print(set1);


    auto it2 = set1.emplace(200);
    cout << "*it2.first:" << *it2.first << "   it2.second:" << it2.second << endl;
    Print(set1);


    return 0;
}

在这里插入图片描述

erase,swap

#include <iostream>
#include <unordered_set>

using namespace std;


void Print(unordered_set<int>& set)
{
    auto it = set.begin();

    while (it != set.end())
    {
        cout << *it << "  ";
        it++;
    }
    cout << endl;
}

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });
    unordered_set<int> set2({ 3, 7, 5, 9, 0, 1, 6 });
    

    set1.erase(set1.begin());//插入 value ,以 hint 为应当开始搜索的位置的非强制建议。
    Print(set1);
    
    set1.erase(9);//移除键等价于 key 的元素(如果存在一个)
    Print(set1);
    
    set1.erase(set1.begin(),set1.end());//set1.erase(set1.begin()++);//移除范围 [first; last) 中的元素,
    Print(set1);

    set1.swap(set2);
    Print(set1);
    Print(set2);


    return 0;
}

在这里插入图片描述

查找

查找函数功能
size_type count( const Key& key ) const;返回拥有比较等于指定参数 key 的关键的元素数,因为此容器不允许重复故为 1 或 0 。
template< class K >size_type count( const K& x ) const;返回键比较等价于指定参数 x 的元素数。
bool contains( const Key& key ) const;检查容器中是否有键等价于 key 的元素。
std::pair<iterator,iterator> equal_range( const Key& key );返回容器中所有键等于 key 的元素范围。范围以二个迭代器定义,第一个指向所需范围的首元素,而第二个指向范围的尾后一位元素。
template< class K >std::pair<iterator,iterator> equal_range( const K& x );返回含有容器中所有键等价于 x 的元素的范围。
#include <iostream>
#include <unordered_set>

using namespace std;

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });
    

    cout << "set1.count(3): " << set1.count(3) << endl;

    auto it = set1.equal_range(7);
    cout <<"*it.first:" <<*it.first << endl;
    cout << "*it.second:"<<*it.second << endl;

    return 0;
}

在这里插入图片描述

桶接口

桶接口功能
local_iterator begin( size_type n );返回指向下标为 n 的桶首元素的迭代器。
local_iterator end( size_type n );返回后随下标为 n 的桶的最后元素的元素的迭代器。
size_type bucket_count() const;返回容器中的桶数。
size_type max_bucket_count() const;返回容器由于系统或库实现限制的能保有的最大桶数。
size_type bucket_size( size_type n ) const;返回下标为 n 的桶中的元素数。
size_type bucket( const Key& key ) const;返回关键 key 的桶的下标。始终会在此桶中找到关键等于 key 的元素(若存在)。
#include <iostream>
#include <unordered_set>

using namespace std;

int main()
{

    unordered_set<int> set1({ 3, 7, 5, 9, 0, 1, 6 });
    
    auto it = set1.begin(0);
    cout << "0号桶的首元素: " << *it << endl;

    it = set1.end(0);//当桶中的元素数量为0时,it会发生越界的行为
    cout << "1号桶的尾元素: " << *(it--) << endl;

    cout << "容器中桶数量: " << set1.bucket_count() << endl;
    cout << "容器中最大桶数量: " << set1.max_bucket_count() << endl;
    cout << "1号下标的桶中的元素数: " << set1.bucket_size(1) << endl;
    cout << "关键字7所在桶的下标: " << set1.bucket(7) << endl;    

    return 0;
}

哈希策略

哈希策略功能
float load_factor() const;返回每个桶元素的平均数,即 size() 除以 bucket_count() 。
float max_load_factor() const;管理最大加载因子(每个桶的平均元素数)。返回最大加载因子。
void max_load_factor( float ml );管理最大加载因子(每个桶的平均元素数)。设置最大加载因子为 ml 。
void rehash( size_type count );设置桶数为 count 并重哈希容器,即考虑桶总数已改变,再把元素放到适当的桶中。
void reserve( size_type count );设置桶数为适应至少 count 个元素,而不超出最大加载因子所需的数,并重哈希容器,即考虑桶数已更改后将元素放进适合的桶。

观察器

观察器功能
hasher hash_function() const;返回对关键哈希的函数。
key_equal key_eq() const;返回比较关键相等性的函数。

非成员函数

非成员函数功能
template< class Key, class Hash, class KeyEqual, class Allocator >
bool operator==( const std::unordered_set<Key,Hash,KeyEqual,Allocator>& lhs, const std::unordered_set<Key,Hash,KeyEqual,Allocator>& rhs );比较二个无序容器的内容。若下列条件成立则二个无序容器 lhs 与 rhs 相等:lhs.size() == rhs.size()从 lhs.equal_range(lhs_eq1) 获得的每组等价元素 [lhs_eq1, lhs_eq2) 拥有在另一容器中从 rhs.equal_range(rhs_eq1) 获得的对应等价元素组 [rhs_eq1, rhs_eq2) ,1) 若容器内容相等则为 true ,否则为 false 。2) 若容器内容不相等则为 true ,否则为 false 。
template< class Key, class Hash, class KeyEqual, class Alloc >void swap( std::unordered_set<Key,Hash,KeyEqual,Alloc>& lhs, std::unordered_set<Key,Hash,KeyEqual,Alloc>& rhs );为 std::unordered_set 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

END!

<think>好的,我现在需要详细解答用户关于C++unordered_setunordered_map返回值的问题。首先,我应该回顾这两个容器的基本概念,然后分别讨论它们的返回值类型和相关成员函数的返回值。 首先,unordered_setunordered_map都是C++ STL中的无序关联容器,基于哈希表实现。它们的返回值主要涉及插入、查找、删除等操作的结果。需要区分它们的返回值类型,比如insert返回的是pair<iterator, bool>,而find返回的是迭代器。 接下来,我需要分点讨论unordered_setunordered_map各自的返回值。对于unordered_set,插入操作的返回值是一个pair,其中包含指向插入元素的迭代器和一个布尔值表示是否插入成功。查找操作返回迭代器,删除操作返回删除的元素数量。另外,像count这样的函数返回0或1,因为unordered_set不允许重复元素。 然后是unordered_map的情况。插入操作同样返回pair<iterator, bool>,但插入的元素是键值对。这里需要注意的是,当插入已存在的键时,返回的布尔值为false。查找操作返回指向键值对的迭代器,访问元素时使用operator[]可能会插入新元素,而at()则抛出异常。删除操作的返回值和unordered_set类似。count也是返回0或1,因为键唯一。 还要注意它们之间的区别,比如unordered_map的元素是键值对,而unordered_set是单一值。此外,operator[]在unordered_map中的行为比较特殊,可能会修改容器,这点需要强调。 需要参考用户提供的引用内容,特别是引用[1]、[2]、[4],这些涉及构造、仿函数和迭代器的实现。比如,引用[2]提到unordered_map使用哈希表并通过仿函数获取键值,这可能影响迭代器的返回值类型。引用[4]中的迭代器实现说明了解引用和访问元素的方式,这对理解返回的迭代器如何操作元素有帮助。 最后,生成相关问题时,要考虑用户可能感兴趣的后续内容,比如性能比较、实际应用场景、有序容器的对比等。确保问题覆盖常见疑问,帮助用户深入理解。</think>### C++ unordered_setunordered_map 返回值详解 #### 一、unordered_set 的返回值 1. **插入操作** `insert(value)` 返回一个 `pair<iterator, bool>`: - `first`:指向插入元素的迭代器 - `second`:布尔值,表示是否插入成功(若元素已存在则为 `false`) 示例: ```cpp auto result = s.insert(5); if (result.second) { cout << "插入成功,位置:" << *result.first << endl; } ``` 2. **查找操作** `find(key)` 返回 **迭代器**: - 找到元素时返回指向该元素的迭代器 - 未找到时返回 `end()` 示例: ```cpp auto it = s.find(3); if (it != s.end()) { cout << "找到元素:" << *it << endl; } ``` 3. **删除操作** `erase(key)` 返回删除的元素数量(0 或 1)[^3]。 示例: ```cpp int count = s.erase(4); // 返回1表示删除成功 ``` 4. **其他操作** - `count(key)`:返回 0 或 1(因集合元素唯一) - `empty()`:返回布尔值表示容器是否为空 - `size()`:返回当前元素数量 --- #### 二、unordered_map 的返回值 1. **插入操作** `insert({key, value})` 返回 `pair<iterator, bool>`: - `first`:指向插入键值对的迭代器 - `second`:布尔值,表示是否插入成功(若键已存在则为 `false`)[^2] 示例: ```cpp auto result = m.insert({"apple", 10}); if (result.second) { cout << "插入键值对:" << result.first->first << "->" << result.first->second << endl; } ``` 2. **查找操作** `find(key)` 返回 **迭代器**: - 迭代器指向 `pair<const Key, Value>` 类型 - 未找到时返回 `end()` 示例: ```cpp auto it = m.find("apple"); if (it != m.end()) { cout << "找到值:" << it->second << endl; } ``` 3. **元素访问** - `operator[]`:返回键关联的值的引用(若键不存在则插入默认值) - `at(key)`:返回值的引用,若键不存在则抛出 `out_of_range` 异常 示例: ```cpp m["banana"] = 20; // 插入或修改值 int num = m.at("apple");// 安全访问 ``` 4. **删除操作** `erase(key)` 返回删除的元素数量(0 或 1)[^3]。 --- #### 三、关键区别 | 操作 | unordered_set | unordered_map | |--------------|--------------------------------|------------------------------------| | 插入返回值 | `pair<iterator, bool>` | `pair<iterator, bool>` | | 查找返回值 | 指向元素的迭代器 | 指向键值对的迭代器 | | 元素类型 | 单个值 | 键值对 `pair<const Key, Value>` | | `operator[]` | 不支持 | 支持,可能隐式插入新键 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值