【问题标题】:Data structure to search name of files and get its path用于搜索文件名并获取其路径的数据结构
【发布时间】:2018-04-24 23:16:16
【问题描述】:

我将以动态方式插入文件名称,大约直到 10 亿个名称。此外,我还想存储文件所在的路径,以便进行以下查询:

  • 搜索是否存储了文件名以获取其路径。
  • 搜索与子字符串匹配的所有文件的名称,有点像类似查询(例如,如果搜索 *o*,它将返回我 joel、hola、ola、oso、osea、algo,如果搜索 aa*,它会返回我 aaab,如果我搜索 *so,它会返回 oso)。
  • 删除文件名。

所以,我正在尝试通过以下方式制作一种 trie 数据结构:

我有 26 个节点(英文字母 az,我不会将所有节点都放在图像中,因为空间)这样如果我插入单词“hola”,那么我会从带有字母 'h 的节点创建一条边' 到带有字母 'o' 的节点,并且其边缘的数据为 1,因为该数字表示深度的级别。此外,在存储'a'的节点中,我将有一个映射结构来存储文件的路径,这是因为我肯定会在包含字母'a'的节点中存储很多路径.

话虽如此,我插入了以下单词:joel、hola、ola、oso、osea、algo、aaab。

我这样做是因为我不希望有很多带有同名字母的节点(例如 a、b 等),但问题是我有很多边和结构需要

内存字节数(我正在使用 C++ 编程),其中 w 是大小为 的字符串。

如您所见,如果我搜索文件“jola”的名称(未插入),则不会返回任何路径,这告诉我们没有存储此类文件。

我该如何改进呢?有什么办法可以减少边数?还是有更好的结构和方法来做到这一点?我很乐意听到任何建议。

【问题讨论】:

  • 要节省更多内存,请考虑使用有向无环字图 (DAWG)。 en.wikipedia.org/wiki/… 通常,您构建一个 trie,然后对其进行优化。
  • 数据结构的目的是什么?它要解决什么问题?
  • 我很确定您的图表对于您的示例不正确(例如,为什么 -> b = 4 ??)。另外,这个数据结构不支持你描述的用例——它如何表明“jola”不是一个词?
  • 所以最后你会得到一个以字母结尾的所有“路径”的列表,该字母存储在附加到该字母节点的单个集合中?听起来您通过构建此数据结构一无所获 - 要验证匹配,您必须迭代集合(希望它将保持排序并且您可以进行二进制搜索),并且对于非匹配,您仍然有很好的机会击中错误的结束节点。不想消极,但这看起来不太有效 - 抱歉。
  • 我真的认为你正在寻找一个directed acyclic word graph (DAWG),这是一个高度优化的树。这个想法是你构建一个普通的 trie,然后应用一些众所周知的优化。我已经看到它用于在大约 1 兆字节的内存中编码 650,000 个单词的英语词典。

标签: optimization data-structures graph trie


【解决方案1】:

我过去解决了一个有点类似的问题,用于存储填字游戏的单词列表,并且非常快速地找到单词。我称它为“超级索引”。我的主要目标是速度,而不是存储大小,但最初的问题并没有说明作者认为的“改进”:也许是大小,也许是速度,也许是算法复杂度。我的方法以相对较小的复杂性产生了巨大的速度,但在存储大小上节省了相当多的空间。方法如下:

  1. 使用树,而不是图表。树中的每个节点最多有 26 个“条目”。每个条目代表字母表中的一个字母并包含到子节点的链接,或者,如果条目属于叶节点,则链接到“有效负载”,在您的情况下是“路径”。因此,当一个节点包含给定字母的条目时,这表示在该位置存在一个带有该字母的“名称”。 (位置是树中节点的深度。)

  2. 按名称长度分隔所有名称,因为这很容易确定。为每个名称长度使用完全独立的树。这意味着在每棵树中,所有叶节点的深度完全相同,并且树中唯一包含附加数据(在您的情况下为路径)的节点是叶节点。这让事情变得非常简单。

所以,搜索算法如下:

  1. 在具有不同名称长度的所有不同树中,使用与您要搜索的“名称”长度相对应的树。
  2. 从您要查找的“名称”的第一个字母开始,在树的根节点处。
  3. 在当前节点中查找当前字母的入口;如果不存在这样的条目,则未找到该名称,完成。否则:
  4. 如果我们已到达叶节点,则已找到名称,返回有效负载,在您的情况下是“路径”。否则:
  5. 转到您要查找的单词的下一个字母;按照从当前节点中找到的条目到下一个子节点的链接;转到第 3 步。

如您所见,这是一个相当简单的算法,并且保证非常快。如果没有任何进一步的优化,存储要求将是每个存储的名称一个“条目”的顺序,一个“条目”将由一个字符和一个指针组成。

然后,可以进行多种优化。例如,“条目”在推理您的数据结构时可能是有用的概念,但在实际实现中可能会完全消失:在每个节点中,您可以有一个“摘要”32 位机器字,其中每个前 26 位表示节点中是否存在相应的字母表,然后是指向子节点(或有效负载)的指针数组,其中包含与摘要字中设置的位一样多的元素。

【讨论】:

    猜你喜欢
    • 2017-07-24
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 2020-06-22
    相关资源
    最近更新 更多