编写代码对树的遍历在开发种是很常见的,DOM,文件夹等其数据结构其实就是一棵树(Tree),一般都是通过递归的方式来进行遍历(叫”递归深度优先算法”), 但是如果树的层次很多,会使程序出现堆栈溢出(Stack Over)异常;其实非递归遍历树的算法也是很简单的,除了可以规避堆栈溢出风险外还有速度快的优点!
在这里我以遍历目录为例,演示遍历树的2种方法:非递归广度优先 算法(就是先找出同层的所有节点), 非递归深度优先 算法(就是先找出一个节点下的所有子子孙孙节点)
废话少数,直接上源码:
package wjw.demo;
import java.io.*;
import java.util.*;
/**
* @author wjw465150@gmail.com
*
*/
public class Main {
public Main() {
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: Main [path name]");
System.exit(0);
}
Main main = new Main();
System.out.println("1.非递归广度优先");
main.doIterator1(args[0]);
System.out.println("--------------------------------------------------------------------");
System.out.println("1.非递归深度优先");
main.doIterator2(args[0]);
}
//非递归广度优先算法
private void doIterator1(String rootPath) throws Exception {
File rootFile = new File(rootPath);
int level = 1;
System.out.println(rootFile.getCanonicalFile());
LinkedList<WrapperFileNodeLevel> list = new LinkedList<WrapperFileNodeLevel>();
File[] childs = rootFile.listFiles();
if (childs != null) {
for (File child : childs) { // 1.先添加第1层的子节点到迭代列表里
list.add(new WrapperFileNodeLevel(child, level + 1));
}
}
WrapperFileNodeLevel wrap;
while (!list.isEmpty()) { // 2. 开始迭代
wrap = list.removeFirst(); // 移除并返回此列表的第一个元素
if (wrap.file.isDirectory()) {
System.out.println(convertLevel2Str(wrap.level) + "[" + wrap.file.getCanonicalPath() + "]");
} else {
System.out.println(convertLevel2Str(wrap.level) + wrap.file.getCanonicalPath());
}
childs = wrap.file.listFiles();
if (childs != null) {
for (File child : childs) {
list.add(new WrapperFileNodeLevel(child, wrap.level + 1)); // 3.有子节点则加入迭代列表
}
}
}
}
//非递归深度优先算法
private void doIterator2(String rootPath) throws Exception {
File rootFile = new File(rootPath);
int level = 1;
System.out.println(rootFile.getCanonicalFile());
LinkedList<WrapperFileNodeLevel> list = new LinkedList<WrapperFileNodeLevel>();
File[] childs = rootFile.listFiles();
if (childs != null) {
for (File child : childs) { // 1.先添加第1层的子节点到迭代列表里
list.add(new WrapperFileNodeLevel(child, level + 1));
}
}
WrapperFileNodeLevel wrap;
while (!list.isEmpty()) { // 2. 开始迭代
wrap = list.removeFirst(); // 移除并返回此列表的第一个元素
if (wrap.file.isDirectory()) {
System.out.println(convertLevel2Str(wrap.level) + "[" + wrap.file.getName() + "]");
} else {
System.out.println(convertLevel2Str(wrap.level) + wrap.file.getName());
}
childs = wrap.file.listFiles();
if (childs != null) {
int pos = 0;
for (File child : childs) {
list.add(pos++, new WrapperFileNodeLevel(child, wrap.level + 1)); // 3.有子节点则加入迭代列表
}
}
}
}
private String convertLevel2Str(int level) {
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < level; i++) {
if (i == level - 1) {
sb.append("|-");
} else {
sb.append(" ");
}
}
return sb.toString();
}
private class WrapperFileNodeLevel {
final File file;
final int level;
/**
* @param file
* @param level
*/
WrapperFileNodeLevel(File file, int level) {
this.file = file;
this.level = level;
}
}
}