首先,关闭所有 profiling 和 DEBUG 开关。这些可以极大地减慢 STL。
如果不是这样,部分问题可能是您的字符串对于字符串的前 80-90% 是相同的。这对 map 来说当然不错,但它适用于字符串比较。如果是这种情况,您的搜索可能需要更长的时间。
例如,在这段代码中 find() 可能会导致几个字符串比较,但每次都会在比较第一个字符直到 "david" 之后返回,然后将检查前三个字符。因此,每次调用最多检查 5 个字符。
map<string,int> names;
names["larry"] = 1;
names["david"] = 2;
names["juanita"] = 3;
map<string,int>::iterator iter = names.find("daniel");
另一方面,在以下代码中,find() 可能会检查 135+ 个字符:
map<string,int> names;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/wilma"] = 1;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/fred"] = 2;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/barney"] = 3;
map<string,int>::iterator iter = names.find("/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/betty");
这是因为字符串比较必须更深入地搜索才能找到匹配项,因为每个字符串的开头都是相同的。
由于您的数据集非常小,因此在比较中使用 size() 对您没有太大帮助。std::map 保持排序,因此可以使用二进制搜索来搜索其元素。每次对 find 的调用应该导致少于 5 次字符串比较未命中,平均 2 次比较命中。但这确实取决于您的数据。如果您的大多数路径字符串的长度不同,那么像 Motti 描述的大小检查可能会有很大帮助。
考虑替代算法时要考虑的事情是您获得了多少“命中”。您的大多数 find() 调用是返回 end() 还是命中?如果您的大多数 find()s 返回 end()(未命中),那么您每次都在搜索整个地图(比较 2logn 字符串)。
Hash_map 是个好主意;它应该将您的搜索时间减少一半左右;更多的失误。
由于路径字符串的性质,可能需要自定义算法,特别是如果您的数据集具有上述代码中的共同祖先。
要考虑的另一件事是如何获取搜索字符串。如果您正在重用它们,将它们编码成更容易比较的东西可能会有所帮助。如果您使用它们一次并丢弃它们,那么这个编码步骤可能太昂贵了。
我曾经(很久以前)使用过类似 Huffman 编码树的东西来优化字符串搜索。在某些情况下,像这样的二进制字符串搜索树可能更有效,但对于像你这样的小集合来说,它相当昂贵。
最后,研究替代 std::map 实现。我听说过一些关于 VC 的 stl 代码性能的坏消息。尤其是 DEBUG 库在每次调用时检查你是不好的。 StlPort曾经是一个不错的选择,但我已经有几年没有尝试过了。我也一直很喜欢Boost。