时间复杂度 当具有复合数据类型(如元组或对)时?
Time complexity when have composite data type such as tuple or pair?
在哈希映射数据结构中,例如C++中的unordered_map:
unodered_map<char, int> mp = { {'a', 10}, {'b', 20} };
if (mp.find('a') != mp.end())
cout << "found you";
我们知道 find(( 方法需要恒定的时间。 但是如果我有复合数据作为键:
unodered_map<tuple<char, string, int>, int> mp = { {'a', "apple", 10}, 100};
if (mp.find( {'a', "apple", 10} ) != mp.end())
cout << "found you";
find(( 方法还会占用常量时间吗? 现在如何评估时间复杂度?
通常,键中的数据字节越多,哈希函数生成值所需的时间就越长(尽管某些哈希函数不会查看每个字节,因此可以降低 big-O 复杂性(。 字节可能更多或更少,因为元组具有更多值,或者元组中的某些元素大小可变(如std::string
(。 同样,对于更多的字节,测试两个键的相等性通常需要更长的时间,这是哈希表的另一个关键操作。
因此,您可以说表的操作与键的大小 - O(K( - 在所有其他条件相同的情况下线性缩放。
但是,更常见的是,你有兴趣比较任何给定插入/擦除/查找的性能与其他类型的容器所需的时间相比,并且在许多其他类型的容器中,随着您添加越来越多的键,性能往往会下降。 这就是人们将哈希表描述为通常具有摊销平均情况 O(1( 操作复杂性的地方,而例如平衡二叉树可能是 O(logN(,其中 N 是存储的元素数。
还有一些其他的考虑因素,例如平衡二叉树中的操作往往涉及比较(即key1 < key2
(,它可能在第一个不同的字节处短路,而哈希函数往往必须处理密钥中的所有字节。
现在,如果在你的问题域中,键的大小可能变化很大,那么从 O(K( 复杂性的角度来考虑是有意义的,但如果键的大小倾向于徘徊在相同的典型范围内 - 无论您存储的键数量如何,那么表属性合理地表示为 O(1( - 删除近恒定的乘法因子。
我认为考虑一个熟悉的类比会有所帮助。 如果你的电话通讯录中存储了100个朋友的名字,或者你有一个大城市的电话簿中有数百万个名字,那么名字的平均长度可能非常相似,所以你可以非常合理地谈论数据结构的大O效率,用"N"来谈论你的数据结构,而忽略它随着名字长度"K"而缩小或增长的方式。
另一方面,如果您正在考虑将任意长度的密钥存储在哈希表中,并且有些人可能会尝试放置百科全书的XML版本,而其他人则存储小说,诗歌或单个单词,那么密钥长度有足够的多样性,可以用K来描述不同的性能是有意义的。
如果您正在存储二进制视频数据的信息,并且有人正在考虑使用原始二进制视频数据作为哈希表键,则同样如此:一些 8k HDR 和数小时长,还有一些微小的动画 GIF。 (更好的方法是生成视频数据的64+位哈希并将其用于密钥,对于大多数实际目的,该密钥将是可靠的唯一;如果处理数十亿个视频,则使用128位(。
理论上的运行时间实际上不是恒定的。在合理的用例下,运行时间仅在平均时保持不变。
在实现中使用哈希函数。如果为在常量时间内运行的元组实现(好的(哈希函数,则find
的渐近运行时间不受影响。
- C++:TypeDef使用元组
- Pybind11:将元组列表从Python传递到C++
- 重载元组索引运算符-C++
- 在C++中,如何通过几种类型从元组中选择多个元素
- 将fold表达式与std::一起用于两个元组
- std::ranges::elements_view,用于自定义类似元组的数据
- 将元组的向量转换/构造为堆
- 专用于 std 元组的模板,而无需用户执行remove_cvref
- 将元组的向量构造成堆
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 将元组类型扩展为可变参数模板?
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- 类内部和外部静态 constexpr 元组之间的差异
- 可变参数模板与使用元组在参数中添加不同的数据对
- 访问和打印元组中的数据,并使用 C++14 使用模板函数显示数据
- boost::包含提升单元的元组的哈希值
- 我正在寻找一种优雅的方式来从元组向量创建tuple_element向量
- 如何在可变参数模板函数中遍历可变参数元组?
- 如何使用 SML 随机生成八进制元组
- 元组的运行时索引