二叉树的先序遍历和后序遍历的应用--输出文件和统计目录大小
一,介绍
本文主要二叉树的两种基本的典型应用:
1) 输出某个文件夹下所有文件名称(可以有子文件夹)---用先序遍历实现
2) 统计某个文件夹的大小(该文件夹下所有文件的大小--用后序遍历实现
二,实现分析
对于问题 1),输出文件名称的过程如下:
如果是文件夹,先输出文件夹名,然后再依次输出该文件夹下的所有文件(包括子文件夹),如果有子文件夹,则再进入该子文件夹,输出该子文件夹下的所有文件名。这是一个典型的先序遍历过程。
对于问题2),统计文件夹的大小过程如下:
若要知道某文件夹的大小,必须先知道该文件夹下所有文件的大小,如果有子文件夹,若要知道该子文件夹大小,必须先知道子文件夹所有文件的大小。
这是一个典型的后序遍历过程。
三,代码实现
输出文件名称:
1 public void list(File f){ 2 list(f, 0); 3 } 4 public void list(File f, int depth){ 5 printName(f, depth); 6 if(f.isDirectory()){ 7 File[] files = f.listFiles(); 8 for (File file : files) { 9 list(file, depth + 1); 10 } 11 } 12 } 13 14 private void printName(File f, int depth){ 15 String name = f.getName(); 16 for(int i = 0; i < depth; i++) 17 System.out.print(" "); 18 if(f.isDirectory()) 19 System.out.println("Dir:" + name); 20 else 21 System.out.println(f.getName() + ":" + f.length()/1024 + "KB"); 22 }
统计文件夹大小程序如下:
1 private long totalSize(File f){ 2 long size = 0; 3 if(f.isFile()) 4 { 5 size = f.length(); 6 } 7 else 8 { 9 File[] files = f.listFiles(); 10 for (File file : files) { 11 size += totalSize(file); 12 } 13 } 14 return size; 15 }
分析:第14行的 return size; 最终返回的是最外层递归(第一层递归时的size),与这篇文章中的查找最大/最小节点方法最终返回的是最里层的递归 形成对比。
其实,因为统计 文件夹A 的大小,需要先算出子文件夹大小,最终各个子文件夹大小之和就是 该文件夹的大小。而递归程序,就是从 文件夹A 开始调用的,遇到子文件夹则递归调用,因此应当返回最外层递归的值。
一个错误的递归版本:
1 private long totalSize(File f, long size){ 2 if(f.isFile()) 3 { 4 size += f.length(); 5 } 6 else 7 { 8 File[] files = f.listFiles(); 9 for (File file : files) { 10 size += totalSize(file, size); 11 } 12 } 13 return size; 14 }
错误的原因如下:
上层目录中文件的大小被重复地统计了。
设统计A目录大小。A目录中包含了一个子目录B,同时包含了c,d,e三个文件。B目录下有 f,g两个文件。
A目录结构如下(大写字母表示目录,小写字母表示文件):
A{B{f,g},c,d,e}
错误的递归方法,在计算B目录的大小时,会把A目录中的c,d,e三个文件的大小也统计进去!!!
整个完整程序如下:
1 import java.io.File; 2 3 public class FileList { 4 public void list(File f){ 5 list(f, 0); 6 } 7 public void list(File f, int depth){ 8 printName(f, depth); 9 if(f.isDirectory()){ 10 File[] files = f.listFiles(); 11 for (File file : files) { 12 list(file, depth + 1); 13 } 14 } 15 } 16 17 private long totalSize(File f){ 18 long size = 0; 19 if(f.isFile()) 20 { 21 size = f.length(); 22 } 23 else 24 { 25 File[] files = f.listFiles(); 26 for (File file : files) { 27 size += totalSize(file); 28 } 29 } 30 return size; 31 } 32 33 /**recursive error 34 private long totalSize(File f, long size){ 35 if(f.isFile()) 36 { 37 size += f.length(); 38 } 39 else 40 { 41 File[] files = f.listFiles(); 42 for (File file : files) { 43 size += totalSize(file, size); 44 } 45 } 46 return size; 47 } 48 */ 49 private void printName(File f, int depth){ 50 String name = f.getName(); 51 for(int i = 0; i < depth; i++) 52 System.out.print(" "); 53 if(f.isDirectory()) 54 System.out.println("Dir:" + name); 55 else 56 System.out.println(f.getName() + ":" + f.length()/1024 + "KB"); 57 } 58 59 public static void main(String[] args) { 60 FileList flist = new FileList(); 61 File f = new File("F:\\学位论文"); 62 flist.list(f); 63 64 long size = flist.totalSize(f); 65 System.out.println(size/1024/1024 + "MB"); 66 } 67 }