【问题标题】:How to do Million level Dictionary Search **(Non-English)**如何进行百万级字典搜索**(非英语)**
【发布时间】:2017-07-05 03:00:19
【问题描述】:

有字典csv文件,百万级数据&非英文(如中文或日文),最大单词可达32bytes

每次我想在文件中搜索单词。

现在我的解决方案是阻止搜索

  1. 先对数据进行排序
  2. 然后我将 N 个数据拆分为 Sqrt(N) 个块,并使用 ftell in C 获取每个块中第一个数据的 文件偏移量,然后将它们存储在一个以这种方式索引文件:(word),(dict中的偏移量)
  3. 每次收到单词搜索请求,我打开Index文件,逐行读取直到发现这个单词在这个Block中,然后我使用fseek重定位到 dict 文件中该块的第一个数据,然后逐行读取,直到我在 dict 中找到数据。

此解决方案是否合适或是否有任何改进空间? 或者有没有其他解决方案?我不知道如何使用哈希或树来搜索文件中的数据。我必须根据要求重新制作它们吗? 谢谢!!!!!!

【问题讨论】:

  • 你的目标是什么?更快的搜索?内存少?你可能想看看tries
  • @TheGreatContini 对中文来说太大了吗? unicode的汉字超过20000个,emm ms级别的搜索和内存占用尽量小?
  • @ENEKaIku 在大多数现代环境中,一百万个 32 字节的字是微不足道的。正如 TheGreatContini 所问的,您想要实现什么目标?您需要对简单的搜索数据结构进行一些研究。通过散列边缘标签,很容易为任意大的字母表构建一个 trie。使用以这种方式构建的 trie,查找包含 N 个字符的单词需要与 N 成比例的时间,并且常数因子非常小。字典的大小无关紧要。如果你不喜欢尝试,那么简单的哈希表和二叉搜索树都会比你的算法做得更好。
  • 你的方法一点也不差。我的第一个想法是使用一个简单的数组,其元素数等于您使用的语言中的字符数(我不知道有多少是中文或日文的)。对于每个元素,您可以存储开始的偏移量。例如,您可以通过减去array[x+1] - array[x] 中的偏移量来知道每个块的大小。然后,您可以使用单词中的第一个字符来识别块并将其读入内存以进行搜索(您可以将free 延迟到下一次搜索并检查以重用当前块)。
  • @Gene 谢谢!但是如何存储 trie 或哈希表呢?是不是和块搜索一样,我得把文件偏移量作为“指针”存入另一个文件?

标签: c file dictionary search


【解决方案1】:

我对此的第一个想法是,对于这种数据集大小来说,一百万并不是一个大数字。使用基本的平衡二分搜索应该是 log2(million) 比较,或者每次搜索大约 20 次比较。保持它尽可能简单,我会将 32 字节的键读入一个包含(键,文件偏移)的结构数组:

struct record {
  uint8_t key[32];
  uint8_t key_length;
  uint64_t file_offset;
};

#define MAX_RECORDS 1000000

struct record my_index[MAX_RECORDS];

然后确保 'my_index' 数组按键排序,这可以使用标准库的 qsort() 函数 (https://linux.die.net/man/3/qsort) 轻松完成。完成后,您可以按照此处https://en.wikipedia.org/wiki/Binary_search_algorithm 中列出的算法实现分而治之的二进制数组搜索...该算法由标准 C 库的 bsearch() 函数 (https://linux.die.net/man/3/bsearch) 实现。

【讨论】:

  • 谢谢!但是如何存储呢?我的意思是如果我想每次都使用这个记录,那么我必须将它从文件加载到内存中吗?
  • 您将读取和解析您的文件,只存储我之前提到的结构数组中的键和偏移量......从那里检索记录数据将是一个打开/搜索/读取序列,或者变得更高级,您还可以 mmap() 偏移量引用的文件区域。
  • ... 您也可以想象将索引数组写入一个单独的文件,您也可以将其加载/更新/存储为二进制数据。旧的 dbm/ndbm/gdbm 文件支持的数据库做了非常相似的事情。
猜你喜欢
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2012-01-16
  • 2013-01-05
  • 1970-01-01
  • 2019-05-09
相关资源
最近更新 更多