【问题标题】:container for quick name lookup用于快速名称查找的容器
【发布时间】:2009-02-21 01:33:06
【问题描述】:

我想存储字符串并为每个字符串分配一个唯一的 ID 号(索引就可以了)。我只需要每个字符串的一份副本,并且需要快速查找。我经常检查表中是否存在字符串,以至于我注意到性能下降。什么是最好的容器,如果字符串存在,我如何查找?

【问题讨论】:

    标签: c++ containers std


    【解决方案1】:

    我建议使用 tr1::unordered_map。它被实现为哈希图,因此它的查找复杂度为 O(1),最坏的情况为 O(n)。如果您的编译器不支持 tr1,还有一个 boost 实现。

    #include <string>
    #include <iostream>
    #include <tr1/unordered_map>
    
    using namespace std;
    
    int main()
    {
        tr1::unordered_map<string, int> table;
    
        table["One"] = 1;
        table["Two"] = 2;
    
        cout << "find(\"One\") == " << boolalpha << (table.find("One") != table.end()) << endl; 
        cout << "find(\"Three\") == " << boolalpha << (table.find("Three") != table.end()) << endl; 
    
        return 0;
    }
    

    【讨论】:

    • 不要在T1中使用unordered_map,它没有reserve方法,如果你在插入阶段插入很多字符串,你将会有很多rehashing。
    • 长字符串的 unordered_map 也比 std::map 最差
    【解决方案2】:

    试试这个:


    (来源:adrinael.net

    【讨论】:

      【解决方案3】:

      试试 std::map。

      【讨论】:

        【解决方案4】:

        首先您必须能够量化您的选择。您还告诉我们,您感兴趣的主要使用模式是查找,而不是插入。

        N 是您希望在表中包含的字符串数,并让C 是所述表中存在的任何给定字符串(或字符串中)的平均字符数对照表进行检查)。

        1. 基于散列的方法的情况下,对于每次查找,您需要支付以下费用:

          • O(C) - 计算您要查找的字符串的哈希值
          • 介于O(1 x C)O(N x C) 之间,其中1..N 是您期望基于哈希键遍历存储桶的成本,这里乘以C 以根据查找键重新检查每个字符串中的字符
          • 总时间:在O(2 x C)O((N + 1) x C)之间
        2. std::map-based 方法(使用红黑树)的情况下,您为每次查找支付以下费用:

          • 总时间:在O(1 x C)O(log(N) x C) 之间 - 其中O(log(N)) 是最大树遍历成本,O(C)std::map 的通用less&lt;&gt; 实现重新检查查找键所需的时间在树遍历期间

        如果N 的值很大,并且没有保证小于 log(N) 冲突的哈希函数,或者如果你只是想安全地玩,你最好使用基于树的 (std::map) 方法。如果 N 很小,请务必使用基于哈希的方法(同时仍确保哈希冲突较低。)

        不过,在做出任何决定之前,您还应该检查:

        【讨论】:

          【解决方案5】:

          要搜索的字符串是静态可用的吗?你可能想看看perfect hashing function

          【讨论】:

            【解决方案6】:

            听起来像一个数组可以正常工作,其中索引是数组的索引。要检查它是否存在,只需确保索引在数组的范围内并且其条目不为 NULL。

            编辑:如果您对列表进行排序,您始终可以使用应该具有快速查找的二进制搜索。

            编辑:另外,如果你想搜索一个字符串,你也可以随时使用std::map&lt;std::string, int&gt;。这应该有一些不错的查找速度。

            【讨论】:

            • 等等,所以你想能够说存在(“my_string”)?
            • 我以为你希望能够做到:C[index] 来获取字符串。
            【解决方案7】:

            最简单的方法是使用 std::map。

            它是这样工作的:

            #include <map>
            using namespace std;
            
            ...
            
               map<string, int> myContainer;
               myContainer["foo"] = 5; // map string "foo" to id 5
               // Now check if "foo" has been added to the container:
               if (myContainer.find("foo") != myContainer.end())
               {
                   // Yes!
                   cout << "The ID of foo is " << myContainer["foo"];
               }
               // Let's get "foo" out of it
               myContainer.erase("foo")
            

            【讨论】:

            • 正如我对@Teran 的回答所评论的那样:难道不是 吗?他想查找给定的 UID,而不是字符串。
            • 他说如果我说对了,他想通过 terans 的评论中的字符串查找答案
            • 好吧,他没有……但我们猜他做到了:)
            【解决方案8】:

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-03-10
              • 1970-01-01
              • 2011-01-16
              • 1970-01-01
              相关资源
              最近更新 更多