2013-11-25 37 views
2

我編寫了這個代碼以遞歸列出c#中的文件和文件夾。以C#遞歸列出文件和文件夾#

  var filesInTheCurrentDirectory = System.IO.Directory.GetFiles(rootFolder); 
      if (!filesInTheCurrentDirectory.Any() && !System.IO.Directory.GetDirectories(rootFolder).ToList().Any()) 
      { 
       return; 
      } 

      filesInTheCurrentDirectory.ToList().ForEach(file => System.IO.File.AppendAllText("e:\\personal\\tests.txt", System.IO.Path.GetFileName(file) + ":" + rootFolder + "\n")); 
      System.IO.Directory.GetDirectories(rootFolder).ToList().ForEach(recursivePrintFolders); 

雖然這只是的偉大工程,問題是:

  1. 我使用遞歸。是這樣的best? (我試着寫了一個非遞歸函數,但是因爲我們不知道什麼是每個文件夾的深度提前)。

  2. 如何評估此功能的性能?是OlogN還是O(n)? (我很困惑,因爲沒有循環的版本。據我,如果兩個for環,我可以把它O(n^2)

任何意見或指導的?

+1

爲什麼不直接使用[正在使用的方法的重載](http://msdn.microsoft.com/zh-cn/library/ms143316(v = vs.110).aspx)您? –

+0

你可以發佈你的非遞歸函數嗎? – liquidsnake786

+0

@DanPuzey更正:這是超負荷:) –

回答

5

用遞歸這樣做的主要問題是:

  1. 如果樹的深度過大,你可能沒有足夠的堆棧空間。儘管擁有深度的文件系統結構是不常見的,但這並不是不可想象的。

  2. 您使用的內存比需要的多,因爲您需要保留大量可以避免的堆棧幀數據。

對於漸進複雜,你在每個節點執行一個操作,不管它的大小,所以它是O(n),其中n爲所有節點,而不是在任何深度的節點。

但是,您可以使用內置方法遍歷整個樹來更有效地處理所有這些問題。這將是比一個解決方案,你會想出更有效的,甚至,如果你是非遞歸,只需使用:

foreach(string file in Directory.EnumerateFiles(path, "*", 
    SearchOption.AllDirectories)) 
{ 
    System.IO.File.AppendAllText("e:\\personal\\tests.txt", 
     System.IO.Path.GetFileName(file) + ":" + rootFolder + "\n") 
} 

雖然這種解決方案很可能不使用遞歸,如果你想知道如何寫一個非遞歸樹遍歷自己,你可以使用一個通用的方法是這樣的:

public static IEnumerable<T> Traverse<T>(
    this IEnumerable<T> source 
    , Func<T, IEnumerable<T>> childrenSelector) 
{ 
    var stack = new Stack<T>(source); 
    while (stack.Any()) 
    { 
     var next = stack.Pop(); 
     yield return next; 
     foreach (var child in childrenSelector(next)) 
      stack.Push(child); 
    } 
} 

你的情況,稱這可能是這個樣子:

var allFiles = new[] { new DirectoryInfo(path) } 
    .Traverse(directory => directory.EnumerateDirectories()) 
    .Select(directory => directory.EnumerateFiles()); 

需要注意的是,雖然這對遍歷不提供完整遍歷的內置樹的樹來說是很好的,但這對於遍歷文件系統來說通常並不理想。您應該使用第一個解決方案,因爲它已經針對遍歷文件系統的特殊情況進行了高度優化。

+0

非常感謝您的指導。正確答案。但是,對不起,我還是不明白你的答案的這一部分。 '你爲每個節點執行一次操作,不管它的大小如何,所以它是O(n)'。你能爲我詳細闡述一下嗎? –

+1

@nowhewhomustnotbenamed。還有什麼可說的。工作量與整個樹中的節點數成正比。具有2倍多節點的樹將花費2x時間遍歷。將單個節點添加到大小爲100的樹與大小爲5的樹添加了相同的「成本」。這使得它是線性的。 – Servy

+0

謝謝。這不合理。此外,「通用非遞歸」版本也很棒。 –

相關問題