Algorithm 广度优先目录遍历:是否可以使用O(logn)内存?

Algorithm 广度优先目录遍历:是否可以使用O(logn)内存?,algorithm,memory,breadth-first-search,space-complexity,Algorithm,Memory,Breadth First Search,Space Complexity,我试图创建一个迭代器,它对特定文件夹中的所有文件和文件夹执行宽度优先遍历。我已经使用深度优先遍历完成了这项工作,它返回,例如: \A \A\1 \A\1\x \A\1\y \A\2 \B \B\1 等等 现在我正在尝试制作一个程序,它将首先返回结果:(或逐级返回) 对于相同的层次结构。但是,我遇到了一个绊脚石:假设我希望这些操作按正确的顺序(具体来说,不是相反的顺序)进行,我无法找到任何方法来执行此操作,而最终不需要O(n)内存,其中n是驱动器上的文件/文件夹数,因为在我看来,我最终需要在某个

我试图创建一个迭代器,它对特定文件夹中的所有文件和文件夹执行宽度优先遍历。我已经使用深度优先遍历完成了这项工作,它返回,例如:

\A
\A\1
\A\1\x
\A\1\y
\A\2
\B
\B\1
等等

现在我正在尝试制作一个程序,它将首先返回结果:(或逐级返回)

对于相同的层次结构。但是,我遇到了一个绊脚石:假设我希望这些操作按正确的顺序(具体来说,不是相反的顺序)进行,我无法找到任何方法来执行此操作,而最终不需要O(n)内存,其中n是驱动器上的文件/文件夹数,因为在我看来,我最终需要在某个时刻将整个驱动器层次结构保留在内存中,而对于DFS,我可以完全忽略以前在层次结构的同一级别上枚举的所有条目


所以我的问题是:有没有比线性更好的方法来使用内存来遍历文件夹?

如果您的平台支持
inode number
的概念,您可以为每个目录存储一个数字,以指示您访问过的特定目录的最大inode编号。如果您以数字顺序访问索引节点,跟踪单个条目将足以知道“下一个”条目在哪里

这是一个小小的收获,因为您仍然需要为系统上的每个目录维护一个inode编号,但是您不需要关心目录的内容


当然,请记住,任何遍历机制都会受到可怕的竞争条件的影响,您必须在一定程度上保证文件系统是静态的,或者您的代码对删除、创建、移动等目录/文件具有弹性。,当您的代码正在运行时。

您是否介意在遍历过程中,当您下面的文件系统发生变化时发生一些奇怪的事情?如果没有,您可以将您在层次结构中的当前位置记录为代表一组索引的O(文件系统深度)整数,然后无效地递增该整数。使用运行长度编码,您可以将O(文件系统的深度)降到O(logn),因为文件系统的深度比θ(logn)差的唯一方法是,如果有很多目录只包含一个对象(另一个目录)。另外,我猜路径长度限制意味着你可以说深度是O(1)。@Steve:嗯,我不能真正锁定文件系统,所以是的,我可以在迭代时容忍更改。(或者至少,我现在不担心。)但我不确定你所说的指数是什么意思——每个指数在系统中代表什么?噢!或者使用O(文件系统的深度)字符串来记录位置,当然,当文件系统在您下面发生变化时,这会使事情变得不那么奇怪,但是仍然比常规的FIFO广度优先遍历有点奇怪。@史蒂夫:我仍然不明白使用字符串如何进行广度优先遍历——我不需要在内存中保留每个级别的整个路径吗?这是O(n)内存,因为路径也包含父文件名。即使我使用了ID而不是路径,这仍然不起作用,因为在理想平衡的目录树上,这只是一个2倍的改进(假设是二叉树,叶子的数量是节点数量的一半)。@Mehrdad:例如,假设您当前正在打印
\B\1
。然后当前索引列表是{1,0}(对于
B
,然后对于
1
)。为了增加这个值,我们观察到在
B
中没有更多的文件,然后观察到根目录中没有更多的文件,因此我们转到{0,0,0},这就是
A\1\x
。有趣的是,我以前没有想到inode编号。然而,这仍然是一个O(n)内存需求,对吗?这是我想在这里避免的事情。@Mehrdad,是的,它仍然是O(N),但在目录的数量上,不是所有的文件。(试图通过其他机制跟踪列表中的位置可能在文件数量上是O(N)。
inode number
并不是严格要求的;您还可以按名称对文件和目录列表进行排序,并以这种方式将位置存储到列表中。这通常是相对于叶数的O(logn)(对于文件系统来说也是如此,它往往具有很高的分支因子)。@Donal Fellows,因为@Mehrdad希望在BFS中遍历,所以我的机制不能仅仅是O(TreeDepth),因为我建议为访问的每个目录存储一个整数。(也许在特定路径耗尽后可以收获一些,但我无法想象这会大大节省内存。)
\A
\B
\A\1
\A\2
\B\1
\A\1\x
\A\1\y