一,介紹
本文主要二叉樹的兩種基本的典型應用:
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 }