我一直在尝试快速锻炼,但我不确定什么是最优的,我希望你们中的一些更有经验的开发人员可以通过你们的数据结构知识提供帮助:-)
基本上我有一个路径列表(例如C:\ inetpub \ wwwroot \,C:\ www \ websites \ vhosts \ somesite.com \,D:\ www-mirror \ websites \ vhosts \ somesite.co。英国),我必须检查我正在处理的当前文件(例如C:\ inetpub \ wwwroot \ styles \ style.css)是否存在于预先配置的路径列表中。
所以我最初的想法是整理我的项目列表并执行CurrentFilename.StartsWith(PreconfigureListOfPathsPathName)。但是我经常在列表中进行迭代,并且由于列表有时包含10个,其他1000个(服务器上的客户端)路径,因此速度会慢下来。
您认为这个问题的快速解决方案是什么?我正在用C#3.5编写,这只是项目的一个小部分(但很关键)。
我考虑过二叉搜索树,分解路径,然后做一个树形图并迭代每个路径。但我不确定它是否正确,因为我们可以有很多节点。
D:\www-mirror\websites\vhosts\somesite.co.uk\
D:\www-mirror\websites\vhosts\somesite.com\
D:\www-mirror\websites\vhosts\somesite.org\
D:\www-mirror\websites\vhosts\somesite.pl\
树形图:
www-mirror->websites->vhosts->somesite* (has 4 nodes)
www-mirror->blah->woah->okay
但它看起来有点不稳定。
答案 0 :(得分:1)
使用预配置的路径初始化HashSet
。然后,对于要测试的每个文件,从末尾开始减少路径并在每次迭代时探测HashSet
:
class PreconfiguredPaths {
private readonly HashSet<string> known = new HashSet<string>();
public PreconfiguredPaths(params string[] paths) {
foreach (var p in paths)
known.Add(Normalize(p));
}
public string Parent(string path) {
path = Normalize(path);
while (path.Length > 0) {
if (known.Contains(path))
return path;
else if (!path.Contains("\\"))
break;
path = Regex.Replace(path, @"\\[^\\]+$", "");
}
return null;
}
private string Normalize(string path) {
return Regex.Replace(path, "\\\\+", "\\").TrimEnd('\\').ToLower();
}
}
例如:
var paths = new PreconfiguredPaths(
@"C:\inetpub\wwwroot\",
@"C:\www\websites\vhosts\somesite.com\",
@"D:\www-mirror\websites\vhosts\somesite.co.uk"
);
string[] files = {
@"C:\inetpub\wwwroot\styles\style.css",
@"F:\foo\bar\baz",
@"D:\",
};
foreach (var f in files)
Console.WriteLine("{0} => {1}", f, paths.Parent(f));
输出:
C:\inetpub\wwwroot\styles\style.css => c:\inetpub\wwwroot F:\foo\bar\baz => D:\ =>
答案 1 :(得分:0)
我怀疑迭代1000个项目的列表实际上是你的表现瓶颈。我怀疑实际上击中磁盘或网络共享正在耗费时间。如果您正在执行磁盘或网络I \ O,则需要在工作线程上执行此操作。只需走1000个物品就不需要复杂的结构。你应该做一些时间来看看你的性能问题究竟在哪里......
如果您要发布当前用于进行迭代的代码,那么也可能有助于获得更好的答案。
答案 2 :(得分:0)
最好的办法是用树模拟允许路径,并将检查的路径视为树遍历。所以你建立了一个像:
这样的结构root
+- C:
| +- inetpub
| +- wwwroot
| +- www
| +- websites
+- D:
+- www-mirror
等等
或者,您可以简单地拥有一个排序的路径列表,并对它们进行二分搜索以找到最接近的匹配(在字符串比较术语中等于或小于)。如果您的字符串以最接近的匹配开头,则它位于允许的目录中。
在这种情况下你必须规范化输入(例如全部小写,确保所有路径分隔符都是一致的等)。
答案 3 :(得分:0)
我想说trie是这个场景可能的最佳数据结构。我想,你可以在网上找到trie实现。如果没有,可以通过以下维基百科轻松编写。
对于trie,/将是默认的节点断路器。因此,每个节点都包含一些路径名,您可以根据数据传输trie。该解决方案可能涉及比较源自特定路径的最大节点数。最糟糕的情况将发生在下面的情况中,您有n个长度路径,最后一个节点包含m个文件。在这种情况下,你实际上是在进行n次遍历+ m次比较,所以它的O(N + M)。如果目录包含均匀分布的文件,则时间将为O(要搜索的路径的长度)。
另一项改进是缓存最近的答案,然后在继续进行测试之前检查它们。