Optimization 用于搜索文件名并获取其路径的数据结构

Optimization 用于搜索文件名并获取其路径的数据结构,optimization,data-structures,graph,trie,Optimization,Data Structures,Graph,Trie,我将以动态的方式插入文件名,大约直到10亿个名称。此外,我还希望存储文件所在的路径,以便执行以下查询: 搜索是否存储了文件名以获取其路径 搜索与子字符串匹配的所有文件的名称,类似于查询(例如,如果搜索*o*,它将返回我joel、hola、ola、oso、osea、algo,如果搜索aa*,它将返回我aaab,如果搜索*so,它将返回oso) 删除文件名 因此,我试图通过以下方式制作一种trie数据结构: 我有26个节点(英文字母a-z,我不打算把所有节点都放在图像中,因为是空格),因此如果我

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

  • 搜索是否存储了文件名以获取其路径
  • 搜索与子字符串匹配的所有文件的名称,类似于查询(例如,如果搜索*o*,它将返回我joel、hola、ola、oso、osea、algo,如果搜索aa*,它将返回我aaab,如果搜索*so,它将返回oso)
  • 删除文件名
因此,我试图通过以下方式制作一种trie数据结构:

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

说到这里,我插入了以下文字:joel、hola、ola、oso、osea、algo、aaab

我这样做是因为我不想有很多sama节点(例如a、b等),但问题是我有很多边和结构需要

字节的内存(我用C++编程),其中w是一个字符串大小

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

我该如何改进这一点?有没有办法减少边的数量?或者有更好的结构和方法来做到这一点?我很乐意听取任何建议


我在过去解决了一个类似的问题,用于存储纵横填字游戏的单词列表,并快速查找单词。我称之为“超级索引”。我的主要目标是速度,而不是存储大小,但最初的问题并没有说明作者认为是什么“改进”:可能是大小,可能是速度,可能是算法复杂性。我的方法以相对较小的复杂度获得了巨大的速度,但在存储大小方面有相当适度的节省。方法如下:

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

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

  • 因此,搜索算法如下所示:

  • 在不同名称长度的所有不同树中,使用与正在搜索的“名称”的长度相对应的树
  • 从要查找的“名称”的第一个字母开始,并在树的根节点处开始
  • 在当前节点中查找当前字母的条目;如果不存在这样的条目,则找不到名称,完成。否则:
  • 如果我们已经到达一个叶节点,那么名称已经被找到,返回有效负载,在您的例子中是一个“路径”。否则:
  • 转到你要找的单词的下一个字母;遵循从当前节点中找到的条目到下一个子节点的链接;转至步骤3
  • 正如您所看到的,这是一个相当简单的算法,而且保证速度非常快。如果没有任何进一步的优化,存储需求将是每个存储的名称一个“条目”,一个“条目”将由一个字符加一个指针组成


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

    为了节省更多的内存,考虑有向无环单词图(DAWG)。通常,您构建一个trie,然后对其进行优化。数据结构的用途是什么?这意味着要解决什么问题?我很确定您的图表对于您的示例是不正确的(例如,why is->b=4??)。此外,此数据结构不支持您描述的用例-它将如何表示“jola”不是一个单词?因此,最终您将有一个以字母结尾的所有“路径”列表,该字母存储在附加到该字母节点的单个集合中?听起来,通过构建此数据结构,您将一无所获—要验证匹配,您必须迭代集合(希望它将保持排序,并且您可以进行二进制搜索),而对于非匹配,您仍然有很好的机会命中假结束节点。不是试图消极,但这看起来不太有效-对不起。我真的认为你在寻找一个,这是一个高度优化的trie。其思想是构建一个普通的trie,然后应用一些众所周知的优化。我曾见过它在大约1兆字节的内存中对一本650000字的英语词典进行编码。