GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing notes.kamacoder.com — C++ unordered_map的rehash机制:负载因子计算、自动扩容触发条件、O(n)重哈希过程、迭代器失效规则、reserve预分配优化 # unordered_map 的 rehash 机制面试官问"unordered_map 什么时候会 rehash",很多人只答"元素多了就会扩容"。但追问"负载因子怎么算""rehash 的复杂度是多少""迭代器会不会失效""reserve 和 rehash 有什么区别"就答不上来了。 # 简要回答unordered_map 底层是哈希表(桶数组 + 链表/红黑树)。负载因子 = # 详细回答负载因子——rehash 的触发条件 负载因子 = 当前元素数 / 桶数量。负载因子越高,每个桶里的链表越长,查找从 O(1) 退化为 O(n)。所以 unordered_map 设了一个上限 rehash 的过程
整个过程是 O(n),n 是元素数量。这就是为什么 unordered_map 的插入是"均摊 O(1)"而不是"严格 O(1)"——大部分插入是 O(1),但偶尔一次插入会触发 O(n) 的 rehash。 迭代器失效规则 rehash 后所有迭代器失效。但元素的引用和指针不失效——因为 unordered_map 是节点式容器,rehash 只是把节点从旧桶摘下来挂到新桶,节点本身的内存地址不变。这和 vector 扩容不同(vector 扩容后引用也失效)。 reserve 和 rehash 的区别
# 知识拓展Q:为什么默认 max_load_factor 是 1.0 而不是更小? 这是空间和时间的权衡。负载因子越小,桶越空,查找越快,但浪费内存越多。1.0 意味着平均每个桶一个元素,是一个比较平衡的选择。Java 的 HashMap 默认是 0.75,更偏向性能。 Q:rehash 会改变元素的相对顺序吗? 会。rehash 后元素在桶中的分布完全重新计算,遍历顺序会变。这也是为什么 unordered_map 叫"无序"——不保证任何遍历顺序,甚至两次遍历之间如果发生了 rehash,顺序都可能不同。 Q:如何避免 rehash 带来的性能抖动? 如果能预估元素数量,在插入前调用 Q:unordered_map 和 map 怎么选? 需要有序遍历或范围查询用 map(红黑树,O(log n))。只需要快速查找/插入用 unordered_map(哈希表,均摊 O(1))。数据量小时 map 可能更快(红黑树常数小),数据量大时 unordered_map 优势明显。 评论验证登录状态... |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |