解决方案只能递归的问题示例

时间:2011-04-30 06:30:07

标签: algorithm recursion iteration

  

可能重复:
  Can every recursion be converted into iteration?

是否存在必须使用递归并且无法迭代执行此操作的问题?例如,删除子文件夹中的文件。

public static boolean deleteFile(String sFilePath)
{
  File oFile = new File(sFilePath);
  if(oFile.isDirectory())
  {
    File[] aFiles = oFile.listFiles();
    for(File oFileCur: aFiles)
    {
       deleteFile(oFileCur.getAbsolutePath());
    }
  }
  return oFile.delete();
}

我想不出上面那个的迭代版本,因为我们必须事先知道实际存在多少级别的文件夹,如果我们引入一个新的子文件夹,我们将不得不更改代码。是它是否可以以不需要将来代码更改的方式制作上述代码的迭代版本?

5 个答案:

答案 0 :(得分:6)

您可以自己使用堆栈来存储必要的变量,而无需递归调用函数。

在这种情况下,人们会对文件树进行深度优先遍历,以便在拥有目录等之前首先删除文件“最深处”。

public static void deleteFile(String sFilePath)
{
  File oFile = new File(sFilePath);
  Stack<File> filesToDelete = new Stack<File>();
  Stack<File> directoriesToDelete = new Stack<File>();

  filesToDelete.push(oFile);

  while (! filesToDelete.empty())
  {
    oFile = filesToDelete.pop();

    if(oFile.isDirectory())
    {
      File[] aFiles = oFile.listFiles();
      for(File oFileCur: aFiles)
      {
        filesToDelete.push(oFileCur);
      } 

      // it's a directory, delete it at the end
      // note that we'll see directories 
      // 'deeper down' later but we'll have
      // to delete them before those 'higher up'
      // so use a stack here to delete them
      // after all non-directories were
      // deleted
      directoriesToDelete.push(oFile);

    }
    else
      // it's a file, delete right now
      oFile.delete();

  }

  // delete the directories
  while (! directories.empty())
    directoriesToDelete.pop().delete();

}

答案 1 :(得分:2)

您总是可以在没有递归的情况下解决问题。那么只有你不能没有递归的事情就是展示递归的工作原理。

您可以使用列表和循环来解决删除子文件夹的示例。

答案 2 :(得分:1)

如果你允许适当的数据结构,总是可以通过引入一个保存原始调用的“返回点”的堆栈来解决这种递归。

答案 3 :(得分:1)

这取决于你的意思迭代。如果你的意思是没有一个自己调用的函数,那么你总是可以通过显式使用堆栈来避免递归。

答案 4 :(得分:0)

虽然在这种情况下队列可能更合适:

def delete(path):
    todo = queue()
    todo.put(path)
    while todo:
        item = todo.get()
        if item.isdir():
           empty = True
           for entry in item.listdir():
               todo.put(entry)
               empty = False
           if empty:
               item.delete()
           else:
               todo.put(item)
        else:
           item.delete()