当使用静态字符串值访问std :: map时,访问时间是否仍为O(log n)?

时间:2013-06-04 12:44:06

标签: c++ performance map stl std

std::map<string, int> dict;
for(int i = 0; i < 300; ++i)
{
    dict["afsfgsdg"] = i*i;
    dict["5t3rfb"] = i;
    dict["fddss"] = i-1;
    dict["u4ffd"] = i/3;
    dict["vgfd3"] = i%3;
}

由于字符串值在编译时已知,编译器是否会在编译时对它们进行哈希处理,而不是在运行时对这些字符串进行哈希处理?

3 个答案:

答案 0 :(得分:6)

std::map不会散列任何内容。它使用比较来查找元素,其O(lg n )界限用于映射中有 n 键时所需的比较次数。它没有表达比较本身的成本。

即。程序可能会使用一些短路的字符串比较,首先进行指针比较,但在最坏的情况下比较的数量将保持对数(当项目位于树中的一个叶子时,典型的红黑色)树实施)。

答案 1 :(得分:3)

  

编译器是否会在编译时对它们进行哈希处理,而不是在运行时对这些字符串进行哈希处理?

不,因为std::map不使用散列,它是红黑树或类似的二叉树。

每次都在树中执行查找。

首先,编译器会将"afsfgsdg"转换为std::string,然后对地图中的字符串进行O(log n)搜索。

答案 2 :(得分:1)

分析渐近性能的算法正在研究必须执行的操作以及它们添加到等式中的成本。为此,您需要首先了解执行的操作是什么,然后评估其成本。

在平衡二叉树中搜索密钥(映射恰好是)需要O(log N)复杂操作。这些操作中的每一个都意味着比较匹配的密钥并且如果密钥不匹配则遵循适当的指针(子)。这意味着总成本与log N乘以这两个操作的成本成比例。以下指针是一个恒定时间操作O(1),比较键取决于键。对于整数键,比较快速为O(1)。比较两个字符串是另一个故事,它需要时间与所涉及的字符串的大小成比例O(L)(其中我故意使用L作为字符串参数的长度而不是更常见的N.

当你将所有成本加起来时,你得到的是使用整数作为键,总成本是O(log N)*(O(1)+ O(1)),相当于O(log N)。 (O(1)隐藏在O符号默默隐藏的常量中。

如果使用字符串作为键,则总成本为O(log N)*(O(L)+ O(1)),其中恒定时间操作被更昂贵的线性操作O(L)隐藏,并且可以转换为O(L * log N)。也就是说,在由字符串键入的地图中定位元素的成本与存储在地图中的元素数量的对数乘以用作键的字符串的平均长度成比例。