我的时间和空间分析对这种算法是否正确?
def find_files(suffix, path):
if suffix == '':
return []
# Base condition
if len(os.listdir(path)) == 0:
return []
path_elements = os.listdir(path)
path_files = [file for file in path_elements if ('.' + suffix) in file]
path_folders = [folder for folder in path_elements if '.' not in folder]
for folder in path_folders:
path_files.extend(find_files(suffix=suffix, path=path + '/' + folder))
return path_files
# Tests
path_base = os.getcwd() + '/testdir'
print(find_files(suffix='c', path=path_base))
说明:文件递归
需求:
目的是编写代码以查找目录下的所有文件(及其下所有目录),这些文件以“ .c”结尾
概要:
为了实现这一点,我使用了find_files将带有suffix(文件扩展名)和path(我们需要搜索的目录路径)的函数。在此功能中,我将在父目录及其所有子目录中递归搜索具有给定扩展名的文件。我将所有具有给定后缀的文件存储在列表中并返回。
时空复杂度:
时间复杂度:
os.listdir(path)将列出给定路径中的所有文件和文件夹。由于必须迭代每个项目才能提供列表,因此需要线性时间复杂度。设epath_elements的长度=>O(len(path_elements))=>O(e)
path_elements = os.listdir(path)
下面的行将通过检查.c文件名中是否存在来查找给定路径中的所有文件。如果s是字符串的长度(文件/文件夹的名称),则O(s)查找具有给定扩展名的文件需要花费时间。因此,f文件数量需要O(f*s)时间。出于这样的实际目的,可以公平地假设文件名不是无限长。因此,我们可以假定s为常数=>O(f * 1)=>O(f)。
path_files = [file for file in path_elements if ('.' + suffix) in file]
同样,遍历g目录将花费线性时间=>O(g)
path_folders = [folder for folder in path_elements if '.' not in folder]
以上3个步骤将采取=>O(e + f + g)=>O(e)。由于,e(len(path_elements))是一个主项,因为它是一个组合path_files和path_folders
对于递归,如果每个级别中k的目录数(branches),depth则递归将采用O(brancher^depth)=>O(k^depth)。但是,对于每个递归调用,都执行上述三个步骤。因此,总时间复杂度为O((k^depth) * e
空间复杂度:
输入空间
后缀-O(1)
路径-O(1)
路径元素+路径文件+路径文件夹=>O(e + f + g)=>O(e)
辅助空间
递归使用称为“调用栈”的东西。当一个函数调用自身时,该函数将进入堆栈的顶部。
在此算法中,仅当递归函数遍历每个目录时,它才被用尽。换句话说,到达时depth。因此O(depth),调用堆栈中需要空间。
总空间复杂度=>输入空间+辅助空间=>O(e + depth)
解决方案
我认为复杂度为O(path_elements),其中path_elements所有对的调用返回的文件和文件夹总数os.listdir()。考虑一个文件夹在一个目录中有四个文件:
folder
zip.c
foo.c
bar.c
bas.c
因此,您的函数调用os.listdir(),该函数返回四个文件。这样n = 4。然后,代码遍历列表以查找找不到文件夹的文件夹,然后再次选择.c文件并将其添加到列表中。
这里的复杂度是O(n)调用os.listdir(),O(n)搜索文件夹,以及O(n)选择.c文件并将它们添加到列表中。总共为O(3 * n),即O(n)。
现在考虑以下目录树:
folder
sub1
zip.c
foo.c
sub2
bar.c
bas.c
So the first call to find_files calls os.listdir(folder), which returns two folders. Each folder makes a recursive call to find_files. Altogether there are three calls to os.listdir(), and each one returns two files, so the total number of items returned by os.listdir() is 6.
Now imagine you had:
folder
sub0
sub1
sub2
sub3
...
sub30
file1.c
The complexity here is still O(n). In this case, n is 31.
The point I'm trying to make here is that you look at each item returned from os.listdir() a constant number of times. Thus, O(n).