【发布时间】:2012-09-20 19:00:32
【问题描述】:
我正在编写一个函数,该函数根据数据库条目表查找目录的完整路径。每条记录都包含一个键、目录的名称和父目录的键(如果您熟悉,它就是 MSI 中的目录表)。我有一个迭代解决方案,但它开始看起来有点讨厌。我以为我可以写一个优雅的尾递归解决方案,但我不确定了。
我将向您展示我的代码,然后解释我面临的问题。
Dictionary<string, string> m_directoryKeyToFullPathDictionary = new Dictionary<string, string>();
...
private string ExpandDirectoryKey(Database database, string directoryKey)
{
// check for terminating condition
string fullPath;
if (m_directoryKeyToFullPathDictionary.TryGetValue(directoryKey, out fullPath))
{
return fullPath;
}
// inductive step
Record record = ExecuteQuery(database, "SELECT DefaultDir, Directory_Parent FROM Directory where Directory.Directory='{0}'", directoryKey);
// null check
string directoryName = record.GetString("DefaultDir");
string parentDirectoryKey = record.GetString("Directory_Parent");
return Path.Combine(ExpandDirectoryKey(database, parentDirectoryKey), directoryName);
}
当我意识到我有问题时,这就是代码的样子(删除了一些小的验证/按摩)。我想尽可能使用记忆来短路,但这需要我对字典进行函数调用以存储递归 ExpandDirectoryKey 调用的输出。我意识到我在那里也有一个Path.Combine 电话,但我认为可以通过... + Path.DirectorySeparatorChar + ... 来规避。
我想过使用一个辅助方法来记忆目录并返回值,以便我可以在上面的函数末尾这样调用它:
return MemoizeHelper(
m_directoryKeyToFullPathDictionary,
Path.Combine(ExpandDirectoryKey(database, parentDirectoryKey)),
directoryName);
但我觉得那是作弊,不会被优化为尾递归。
有什么想法吗?我应该使用完全不同的策略吗?这根本不需要是一个超级高效的算法,我只是很好奇。我正在使用 .NET 4.0,顺便说一句。
谢谢!
附:如果您想知道我的终止条件,请不要担心。我用根目录预播字典。
【问题讨论】:
-
无论如何,使用
+运算符进行字符串连接不会使其成为尾调用——函数中的最后一次调用将是+运算符,而不是递归调用。跨度>
标签: c# .net tail-recursion memoization