40、`std::unordered_set` 如何处理元素的删除?

1. 删除元素的核心方法

在 C++ 中,std::unordered_set 提供了以下删除元素的方法:

  • 通过迭代器删除
    语法:iterator erase(const_iterator pos)
    作用:删除指定位置的元素,返回被删元素的下一个有效迭代器。
    时间复杂度:平均 O ( 1 ) O(1) O(1),最坏 O ( n ) O(n) O(n)(哈希冲突严重时)。

  • 通过键值删除
    语法:size_type erase(const Key& key)
    作用:删除与键值匹配的元素,返回实际删除的数量(0 或 1)。
    时间复杂度:平均 O ( 1 ) O(1) O(1)

  • 范围删除
    语法:iterator erase(const_iterator first, const_iterator last)
    作用:删除迭代器区间 [ f i r s t , l a s t ) [first, last) [first,last) 内的元素,返回 last 的下一个迭代器。

2. std::unordered_set 删除元素的底层行为分析

  • 哈希表定位

    删除元素时,首先通过哈希函数计算键值的哈希值,定位到对应的桶。例如,删除元素 x 的哈希值满足:
    在这里插入图片描述

​ (其中 n 是当前桶的数量)

  • 冲突处理

    若桶内因哈希冲突存在链表或类似结构(开链法),需遍历该结构找到目标元素。例如,删除链表中的节点时,直接调整指针完成移除操作,时间复杂度为 O(k)(k 为桶内元素数量)。

  • 内存与结构变化

    • 直接移除元素:底层哈希表不会保留「已删除」标记,而是直接释放内存。

    • 桶数量调整:删除操作不会自动触发缩容(即减少桶数量),需手动调用 rehash()shrink_to_fit() 来优化内存。

3. 关键注意事项

  • 迭代器失效:删除元素可能导致部分迭代器失效(尤其是被删元素的迭代器),但其他迭代器仍有效。
  • 安全删除模式:在循环中删除元素时,需使用 it = s.erase(it) 更新迭代器,避免直接递增导致未定义行为。
  • 性能特性:平均时间复杂度为 O ( 1 ) O(1) O(1),但若哈希表负载因子过高,可能触发重哈希,导致性能下降。

4. 代码示例

#include <unordered_set>
#include <iostream>

int main() {
    std::unordered_set<int> s = {1, 2, 3, 4, 5};

    // 通过键值删除
    s.erase(3); // 删除元素3

    // 通过迭代器删除
    auto it = s.find(4);
    if (it != s.end()) {
        s.erase(it); // 删除元素4
    }

    // 遍历删除偶数
    for (auto it = s.begin(); it != s.end();) {
        if (*it % 2 == 0) {
            it = s.erase(it); // 安全删除并更新迭代器
        } else {
            ++it;
        }
    }

    // 输出剩余元素
    for (int x : s) {
        std::cout << x << " "; // 输出: 1 5
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值