实验说明
这个实验的要求是实现 Count-min sketch,代码中给出了定义,需要填写部分函数的实现,整体难度不大,主要是需要熟悉 C++ 的语法。
项目的编译环境通过 Docker 进行配置和管理,以下为 Dockerfile 内容:
1 | FROM ubuntu:24.04 |
Count-min sketch
这是一种利用哈希函数进行计数的数据结构,用少量的开销对重复出现的目标进行计算,但会损失部分精确度。查看 SPEC 可以很清楚地搞明白其工作原理。
在具体实现中遇到的几个问题耗时较多:
在添加了新的数据结构后,忘了在移动构造和移动赋值函数中进行相应处理
hash_function_ 捕获 this 导致无法通过 std::move 移动
1
2
3
4
5
6/** @fall2025 PLEASE DO NOT MODIFY THE FOLLOWING */
// Initialize seeded hash functions
hash_functions_.reserve(depth_);
for (size_t i = 0; i < depth_; i++) {
hash_functions_.push_back(this->HashFunction(i));
}这导致两个后果:
(1) lambda 的捕获结构里包含原对象的 this
即使对整个
hash_functions_执行:1
std::move(hash_functions_);
lambda 内部捕获的
this依然指向原对象,不会发生语义上的“移动”。(2) 移动后 hash 函数依旧引用旧对象,导致未定义行为(UB)
因此正确做法是:
🟦 在移动构造 / 移动赋值中必须重新构造
hash_functions_,而不是简单移动。TopK(k, &candidates)这个函数的理解出了问题❌ 错误理解:
以为 TopK 会先把 candidates 插入 sketch 再计算 top-k。
✔️ 正确含义:
candidates 早已被插入并计数完毕,
TopK 只是从这些候选项中根据当前 sketch 的估计值选出计数最高的 k 个。