Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;-用于大量可搜索数据的高效容器?_C++_String_Search_Performance - Fatal编程技术网

C++ C++;-用于大量可搜索数据的高效容器?

C++ C++;-用于大量可搜索数据的高效容器?,c++,string,search,performance,C++,String,Search,Performance,我正在为一个大学项目实施一个基于文本的拼字游戏版本 我的字典相当大,大约有40万字(std::string) 如果我选择一个向量(O(n)),搜索一个有效的单词在效率上会非常糟糕。有什么好的选择吗?记住,我是大一新生。没什么太复杂的 谢谢你的时间 Francisco如果您想查找标准库中的内容,可以使用std::set并将单词作为键。这将给你对数搜索时间 由于您的词典可能是静态的(即创建一次且未修改),因此您也可以使用std::vector,使用std::sort对其进行排序,然后对排序后的向量使

我正在为一个大学项目实施一个基于文本的拼字游戏版本

我的字典相当大,大约有40万字(
std::string

如果我选择一个
向量
(O(n)),搜索一个有效的单词在效率上会非常糟糕。有什么好的选择吗?记住,我是大一新生。没什么太复杂的

谢谢你的时间


Francisco

如果您想查找标准库中的内容,可以使用
std::set
并将单词作为键。这将给你对数搜索时间

由于您的词典可能是静态的(即创建一次且未修改),因此您也可以使用
std::vector
,使用
std::sort
对其进行排序,然后对排序后的向量使用
std::binary\u search
查找单词。这还将提供对数搜索时间,并且可能比
更节省空间


如果您想实现自己的数据结构,trie将是一个不错的选择。

std::set是一个很自然的选择,因为它几乎不需要使用向量。即便如此,我还是会教你一些你在成为专业人士之前通常不会学到的东西。不要过早地优化。我在一台现代计算机上打赌,在40K字符串向量中查找线性字典需要0.001秒

在一组中,它是O(logn),可能需要0.00001秒


STL中没有的内容完全是浪费时间。不要把10美元的工作量花在一个10美分的问题上

如果向量已排序,则可以使用测试字典中是否存在给定的单词。

a或将为您提供搜索时间和插入时间,这些时间与正在搜索的字符串长度成线性关系

(请注意,对于任何搜索算法,搜索字符串长度的线性都是最好的,因为比较或散列字符串的长度是线性的——因此,运行时间中字符串长度的线性部分通常不包括在二叉树二叉搜索的运行时间中。)s、 或线性搜索。)


如果您的库中还没有这些解决方案,那么这些解决方案可能会有些过分。

使用
std::tr1::unordered\u集,这样可以提供恒定时间的查找。(根据我的另一个答案,字符串长度是线性的。)

数据结构的用途是什么?您想用它做什么

  • 检查列表中是否有完整的单词,如“tempest”
  • 找到所有以“t”开头和结尾的七个字母的单词吗
  • 找到所有以“t”开头和结尾的七个字母的单词,这些单词可以由一组给定的字母组成
第一个问题是,如果您正在为一组人类玩家实施某种裁判,即一些实体根据官方词典检查建议的单词。基本数据结构,如
std::map
std::set
std::vector
,已经由其他人建议,它们本身就足以满足这一要求目的

第二个和第三个问题是你在写一个玩家时需要回答的问题。在这里,你可能要考虑每一个字母位置的26个集合,每个集合在给定的位置上用给定的字母保持单词。当需要时,你需要额外的代码来计算交叉点,并且可以检查你的单词上的字母。机架


更新:在对原始问题的评论中,OP明确表示,他只需检查字典中是否有单词。这是我上面问的第一个问题,任何标准高效数据结构都可以。

我做了一些分析,得到了以下结果(MSVS 2008,/O2,发布版本,单独启动.exe)

编辑-现在我意识到我实际上完成了我的第一次测试,因为我没有拆分构建和搜索测试。虽然它没有更改“获胜者”,但我做了一些新测试。下面是拆分测试的结果

首先,如果几乎没有坏的搜索请求(400万次好的搜索尝试)

此分析表明,您应该使用“普通”容器变体而不是“多”,并且您应该选择
无序集
。它在构建时间和搜索操作时间方面都非常好

下面是另一个案例的结果(猜测,这不是关于你的应用程序,而是关于它本身),当坏搜索的数量等于好搜索的数量(等于200万)时,胜利者保持不变

还要注意的是,对于静态字典,
vector
set
性能更好(尽管需要更多的初始化时间),但是如果必须添加元素,它会很糟糕

测试代码:

TEST(Containers, DictionaryPrepare) {
   EXPECT_FALSE(strings_initialized);
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      strings.push_back(generate_string());
   }
}

TEST(Containers, VectorPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      vec.push_back(strings[i]);
   }
   sort(vec.begin(), vec.end());
}

TEST(Containers, SetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      set.insert(strings[i]);
   }
}

TEST(Containers, MultisetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      multiset.insert(strings[i]);
   }
}

TEST(Containers, UnorderedSetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      uo_set.insert(strings[i]);
   }
}

TEST(Containers, UnorderedMultisetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      uo_multiset.insert(strings[i]);
   }
}

TEST(Containers, VectorSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      std::binary_search(vec.begin(), vec.end(), strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      std::binary_search(vec.begin(), vec.end(), NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, SetSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      set.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      set.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, MultisetSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      multiset.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      multiset.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, UnorderedSet) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      uo_set.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      uo_set.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, UnorderedMultiset) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      uo_multiset.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      uo_multiset.find(NONEXISTENT_ELEMENT);
   }
}
测试(容器、字典准备){
EXPECT\u FALSE(字符串\u初始化);
对于(大小i=0;i<总元素数;++i){
strings.push_back(generate_string());
}
}
测试(容器、矢量准备){
对于(大小i=0;i<总元素数;++i){
向量推回(字符串[i]);
}
排序(vec.begin(),vec.end());
}
测试(容器、设置和准备){
对于(大小i=0;i<总元素数;++i){
插入(字符串[i]);
}
}
测试(容器、多台准备){
对于(大小i=0;i<总元素数;++i){
多集插入(字符串[i]);
}
}
测试(容器,无序设置准备){
对于(大小i=0;i<总元素数;++i){
uo_集合插入(字符串[i]);
}
}
测试(容器,无序多集准备){
对于(大小i=0;i<总元素数;++i){
uo_multiset.insert(字符串[i]);
}
}
测试(容器、矢量搜索){
对于(大小i=0;i<总搜索数;++i){
二进制搜索(vec.begin()、vec.end()、字符串[rand()%TOTAL_ELEMENTS]);
}
对于(尺寸i=0;i<
[ RUN      ] Containers.DictionaryPrepare
[       OK ] Containers.DictionaryPrepare (235 ms)
[ RUN      ] Containers.VectorPrepare
[       OK ] Containers.VectorPrepare (718 ms)
[ RUN      ] Containers.SetPrepare
[       OK ] Containers.SetPrepare (578 ms)
[ RUN      ] Containers.MultisetPrepare
[       OK ] Containers.MultisetPrepare (579 ms)
[ RUN      ] Containers.UnorderedSetPrepare
[       OK ] Containers.UnorderedSetPrepare (265 ms)
[ RUN      ] Containers.UnorderedMultisetPrepare
[       OK ] Containers.UnorderedMultisetPrepare (375 ms)
[ RUN      ] Containers.VectorSearch
[       OK ] Containers.VectorSearch (3375 ms)
[ RUN      ] Containers.SetSearch
[       OK ] Containers.SetSearch (3656 ms)
[ RUN      ] Containers.MultisetSearch
[       OK ] Containers.MultisetSearch (3766 ms)
[ RUN      ] Containers.UnorderedSet
[       OK ] Containers.UnorderedSet (875 ms)
[ RUN      ] Containers.UnorderedMultiset
[       OK ] Containers.UnorderedMultiset (1016 ms)
[----------] 11 tests from Containers (15438 ms total)
TEST(Containers, DictionaryPrepare) {
   EXPECT_FALSE(strings_initialized);
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      strings.push_back(generate_string());
   }
}

TEST(Containers, VectorPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      vec.push_back(strings[i]);
   }
   sort(vec.begin(), vec.end());
}

TEST(Containers, SetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      set.insert(strings[i]);
   }
}

TEST(Containers, MultisetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      multiset.insert(strings[i]);
   }
}

TEST(Containers, UnorderedSetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      uo_set.insert(strings[i]);
   }
}

TEST(Containers, UnorderedMultisetPrepare) {
   for (size_t i = 0; i < TOTAL_ELEMENTS; ++i) {
      uo_multiset.insert(strings[i]);
   }
}

TEST(Containers, VectorSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      std::binary_search(vec.begin(), vec.end(), strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      std::binary_search(vec.begin(), vec.end(), NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, SetSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      set.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      set.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, MultisetSearch) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      multiset.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      multiset.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, UnorderedSet) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      uo_set.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      uo_set.find(NONEXISTENT_ELEMENT);
   }
}

TEST(Containers, UnorderedMultiset) {
   for (size_t i = 0; i < TOTAL_SEARCHES; ++i) {
      uo_multiset.find(strings[rand() % TOTAL_ELEMENTS]);
   }
   for (size_t i = 0; i < TOTAL_BAD_SEARCHES; ++i) {
      uo_multiset.find(NONEXISTENT_ELEMENT);
   }
}
typedef std::vector<std::string> Word_Container;
typedef std::map<unsigned int, Word_Container *> Index_Table;
Index_Table alpha_array[26]; // ASCII A - Z.
bool found = false;
if (p_word_container)
{
    found = std::binary_search(p_word_container->begin(), p_word_container->end(), word);
}