2016-11-29 6 views
2

非再帰的にこの再帰的ループを変更するには? 私はこの方法が簡単な方法だと知っていますが、私はこの解決法の非再帰的な方法に興味があります。再帰のないフォルダツリーを歩くC#

using System; 
using System.IO; 

namespace NonRecursion { 
    class NonRecursion { 
     static void Main() { 
      string createPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 

      string getPath = createPath + @"\folder"; 
      GetDirsPath(getPath); 

      Console.ReadKey(); 
     } 

     static void GetDirsPath(string getPath) { 
      string[] dirs = Directory.GetDirectories(getPath); 

      for (int i = 0; i < dirs.Length; i++) { 
       Console.WriteLine(dirs[i]); 
       GetDirsPath(dirs[i]); 
      } 
     } 
    } 
} 

この機能のみを変更できますか?

static void GetDirsPath(string getPath) { 
      string[] dirs = Directory.GetDirectories(getPath); 

      for (int i = 0; i < dirs.Length; i++) { 
       Console.WriteLine(dirs[i]); 
       GetDirsPath(dirs[i]); 
      } 
     } 
+2

ヒント: 'GetDirsPath'のキュー<>またはスタック<>を使いたい – Sean

+5

これはエクササイズですか?これがエクササイズでない場合、あなたのために歩く[GetDirectories](https://msdn.microsoft.com/en-us/library/ms143314(v = vs.110).aspx)のバージョンを見てください。サブフォルダツリーを作成し、すべてを単一の呼び出しで返します – Steve

+0

そして、幅優先でも深み優先でも、必要なトラバーサルの種類によってキューとスタックを選択する必要があります。 –

答えて

3

これはどう:

public static IEnumerable<string> AllFolders(string root) 
{ 
    var folders = new Stack<string>(); 
    folders.Push(root); 

    while (folders.Count > 0) 
    { 
     string folder = folders.Pop(); 
     yield return folder; 

     foreach (var item in Directory.EnumerateDirectories(folder)) 
      folders.Push(item); 
    } 
} 

テストコード(コンソールアプリケーション):

public static IEnumerable<string> AllFolders(string root) 
{ 
    var folders = new List<string> {root}; 

    while (folders.Count > 0) 
    { 
     string folder = folders[folders.Count - 1]; 
     folders.RemoveAt(folders.Count-1); 
     yield return folder; 
     folders.AddRange(Directory.EnumerateDirectories(folder)); 
    } 
} 

これらの両方の仕事:

static void Main() 
{ 
    foreach (var dir in AllFolders("<your root folder here>")) 
    { 
     Console.WriteLine(dir); 
    } 
} 

はここList<string>を使用して別のアプローチです同じ方法:

まだ出力されていないディレクトリのリスト(またはスタック)をルートディレクトリから管理します。

アルゴリズムは、スタック/リストから最上位(スタック)または最後(リスト)ディレクトリを削除して出力します。次に、そのディレクトリのすべてのサブディレクトリをリスト/スタックに追加し、リスト/スタックが空になるまで繰り返します。

特に、List<>バージョンは実際にはList<>Stack<>として使用しているため、アルゴリズム的には同じです。

string getPath = createPath + @"\folder"; 

var allDirectories = Directory.GetDirectories(getPath, "*.*", System.IO.SearchOption.AllDirectories); 

が得るそれらを反復処理するには:あなたはGetDirectoriesメソッドを使用することができます

static void GetDirsPath(string getPath) 
{ 
    var dirs = new List<string> { getPath }; 

    while (dirs.Count > 0) 
    { 
     string dir = dirs[dirs.Count - 1]; 
     dirs.RemoveAt(dirs.Count - 1); 
     Console.WriteLine(dir); 
     dirs.AddRange(Directory.EnumerateDirectories(dir)); 
    } 
} 
+0

これは動作しますが、私はGetDirPath関数を変更したいだけです。 –

+0

「これはどうですか」は私にとっては「これを試してみてください」と似ています。私はたくさん試してみることができますので、 "試してみてください"という回答は好きではありません。あなたの答えはOPの回答とは非常に異なるので、あなたは自分の再帰コードを非再帰的なものに変換していないのですが、すべてを書き直したようです。 –

+1

@ Mr.Pro 'GetDirsPath()'に最小限の変更を加えたバージョンを追加しました。 –

1

foreach (string dir in allDirectories) 
{ 
    Console.WriteLine(dir); 
} 

あなただけGetDirsPath()方法に最小限の変更を加えたい場合は

https://msdn.microsoft.com/en-us/library/bb513869.aspx

+1

私はこのメソッドを知っていますが、私はGetDirPath関数を変更したいだけです。 –