我在列表中有一串字符串路径,如[“x1 / x2 / x3”,“x1 / x2 / x4”,“x1 / x5”]。 我需要从这个列表中构造一个树状结构,可以迭代得到一个漂亮的打印树。 像这样
x1
/ \
x5 x2
/ \
x3 x4
任何想法/建议? 我相信可以通过处理字符串列表来解决问题EDIT:选择的正确答案是优雅的实现,其他建议也很好。
答案 0 :(得分:32)
遵循可访问树的天真实现的实现:
class Tree<T> implements Visitable<T> {
// NB: LinkedHashSet preserves insertion order
private final Set<Tree> children = new LinkedHashSet<Tree>();
private final T data;
Tree(T data) {
this.data = data;
}
void accept(Visitor<T> visitor) {
visitor.visitData(this, data);
for (Tree child : children) {
Visitor<T> childVisitor = visitor.visitTree(child);
child.accept(childVisitor);
}
}
Tree child(T data) {
for (Tree child: children ) {
if (child.data.equals(data)) {
return child;
}
}
return child(new Tree(data));
}
Tree child(Tree<T> child) {
children.add(child);
return child;
}
}
访客模式的接口:
interface Visitor<T> {
Visitor<T> visitTree(Tree<T> tree);
void visitData(Tree<T> parent, T data);
}
interface Visitable<T> {
void accept(Visitor<T> visitor);
}
访客模式的示例实现:
class PrintIndentedVisitor implements Visitor<String> {
private final int indent;
PrintIndentedVisitor(int indent) {
this.indent = indent;
}
Visitor<String> visitTree(Tree<String> tree) {
return new IndentVisitor(indent + 2);
}
void visitData(Tree<String> parent, String data) {
for (int i = 0; i < indent; i++) { // TODO: naive implementation
System.out.print(" ");
}
System.out.println(data);
}
}
最后(!!!)一个简单的测试用例:
Tree<String> forest = new Tree<String>("forest");
Tree<String> current = forest;
for (String tree : Arrays.asList("x1/x2/x3", "x1/x2/x4", "x1/x5")) {
Tree<String> root = current;
for (String data : tree.split("/")) {
current = current.child(data);
}
current = root;
}
forest.accept(new PrintIndentedVisitor(0));
输出:
forest x1 x2 x3 x4 x5
答案 1 :(得分:11)
只需用分隔符拆分每个路径,然后逐个将它们添加到树结构中
即如果'x1'
不存在,请创建此节点,如果确实存在,请转到该节点并检查是否有子'x2'
等等...
答案 2 :(得分:4)
我一次把树做成一个字符串。
制作一个空树(有一个根节点 - 我假设可能有一个类似“x7 / x8 / x9”的路径)。
取第一个字符串,将x1添加到根节点,然后将x2添加到x1,然后将x3添加到x2。
取第二个字符串,看到x1和x2已经存在,将x4添加到x2。
为您拥有的每条路径执行此操作。
答案 3 :(得分:2)
创建一个对象节点,其中包含父节点(Node)和子节点列表(节点)。
首先使用“,”拆分字符串。对于每个拆分的字符串,您使用“/”拆分字符串。 在根列表中搜索第一个节点标识符(例如x1)。 如果可以找到它,请使用该节点查找下一个节点标识符(例如x2)。
如果找不到节点,请将节点添加到您在现有列表中找到的最后一个节点。
创建列表结构后,您可以将列表打印到屏幕上。我会把它递归。
未测试,只是一个动画
public void print(List nodes, int deep) {
if (nodes == null || nodes.isEmpty()) {
return;
}
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < deep; i++) {
buffer.append("---");
}
for (Iterator iterator = nodes.iterator(); iterator.hasNext();) {
Node node = (Node)iterator.next();
System.out.println(buffer.toString() + " " + node.getIdentifier());
print(node.getChildren(), deep + 1);
}
}
答案 4 :(得分:0)
为数组中的每个字符串创建树。 只需分开&#39; /&#39; ,检查树中是否存在节点,如果存在则继续...否则创建一个新节点并在父节点的子节点中添加该节点。
使用递归迭代。
以下是树节点的模型。
Class Node{
string name;
List<Node> childrens;
Node(string name){
this.name = name;
this.childrens = new List<Node>();
}
}
答案 5 :(得分:0)
这是我从路径(文件夹)结构中做树的方式。也许应该以基本的逻辑帮助某人。
节点:
public class Node {
private String path;
private List<Node> children;
public Node(String path) {
this.path = path;
children = new ArrayList<>();
}
public String getName() {
return getName(path);
}
private String getName(String path) {
String[] split = path.split("\\\\");
return split[split.length - 1];
}
public void addChild(Node child) {
children.add(child);
}
public List<Node> getChildren() {
return children;
}
public String getPath() {
return path;
}
}
FilesTree:
public class FilesTree {
private static final Logger log = Logger.getLogger(FilesTree.class.getName());
private FilesTree() {}
private static void createTree(Node root, List<String> paths) {
for (String path : paths) {
addNode(root, Arrays.asList(path.split("\\\\")), "");
}
}
private static void addNode(Node node, List<String> path, String nodePath) {
if (!path.isEmpty()) {
nodePath = nodePath.equals("") ? path.get(0) : String.format("%s\\%s", nodePath, path.get(0));
}
if (node.getChildren().isEmpty() && path.size() == 1) {
node.addChild(new Node(nodePath));
} else if (!node.getChildren().isEmpty()) {
for (Node actual : node.getChildren()) {
if (actual.getName().equals(path.get(0))) {
addNode(actual, path.subList(1, path.size()), nodePath);
return;
}
}
node.addChild(new Node(nodePath));
} else {
log.info("Without children but with size: " + path.size());
}
}
}