I'm trying to use a non-recursive depth-first-search approach to read directories and build nested sets. I need to assign left, right, and depth values to the path of the given directory(Files at the same directory level are in no particular order). I have now completed the assignment of depth, left and right to the Leaf node. But I'm confused about how do I get the right-hand value of a non-leaf node.
Here's what I hope to achieve, and what I've already done:
A: Given a directory, where |== stands for folder; |-- stands for file. (You can replace it with your own directory)
|==resources
|==data
|==table_design
|==mapper
|==server
|--ServerMapper.xml
|==source
|--AMapper.xml
|--bootstrap.properties
|--logback-spring.xml
B: Expected result
0 1|||\resources|||20
1 2|||\resources\data||5
2 3|||\resources\data\table_design|||4
1 6|||\resources\mapper|||15
2 7|||\resources\mapper\server|||10
3 8|||\resources\mapper\server\ServerMapper.xml|||9
2 11|||\resources\mapper\source|||12
2 13|||\resources\mapper\AMapper.xml|||14
1 16|||\resources\bootstrap.properties|||17
1 18|||\resources\logback-spring.xml|||19
C: My implementation
- entity
static class MyObject {
private int left;
private int right;
private int depth;
private String path;
}
- My depth-first-search logic
private static void dfs(File root) {
if (root == null) {
return;
}
int depth = 0;
int index = 1;
Stack<File> stack = new Stack<>();
//Indicates whether the node has been pushed onto the stack
Map<File, MyObject> map = new LinkedHashMap<>();
stack.add(root);
MyObject rootObj = new MyObject();
rootObj.setPath(root.getAbsolutePath());
rootObj.setDepth(depth);
rootObj.setLeft(index++);
map.put(root, rootObj);
while (!stack.isEmpty()) {
File cur = stack.pop();
depth--;
File[] files = cur.listFiles();
if (files != null) {
//Execute as soon as the next node is found
for (File next : files) {
//The next node is pushed if it has not been accessed
if (!map.containsKey(next)) {
depth++;
stack.push(cur);
depth++;
stack.push(next);
MyObject obj = new MyObject();
obj.setLeft(index++);
obj.setPath(next.getAbsolutePath());
obj.setDepth(depth);
if (!next.isDirectory()) {
obj.setRight(index++);
}
map.put(next, obj);
break;
}
}
}
}
System.out.println("depth" + "\t left|||path|||right");
for (MyObject value : map.values()) {
System.out.println(value.getDepth() + "\t" + value.getLeft() + "|||" + value.getPath() + "|||" + value.getRight());
}
}
- my output
0 1|||\resources|||0
1 2|||\resources\bootstrap.properties|||3
1 4|||\resources\data|||0
2 5|||\resources\data\table_design|||6
1 7|||\resources\logback-spring.xml|||8
1 9|||\resources\mapper|||0
2 10|||\resources\mapper\server|||0
3 11|||\resources\mapper\server\UserMapper.xml|||12
2 13|||\resources\mapper\source|||0
2 14|||\resources\mapper\SourceJobMapper.xml|||15
I finished the data's build.