如何将平面数据结构显示为分层数据结构(Java)?

我最近在一份工作的实际测试中遇到了这个问题。

假设您有一个像这样的平面数据结构:

**Category** **Name** **Parent** 1 electronics 0 2 Television 1 3 21inch 2 4 23inch 2 5 LCD display 2 6 player 1 7 mp3player 6 8 vcd player 6 9 dvd player 6 10 hd quality 8 

现在从上面的平面数据结构我们想要显示类似下面的分层树结构。

  -Electronics | -Television | | -21 inch | | -23 inch | | -lcd display | -Player | | -mp3player | | -vcdplayer | | | -HD display | | -DVD player 

然后如果我在我的数组中添加另一个条目,如:

 11 Test 3 

那么它应该显示在21inch以下的Test条目。

所以对于这种事情,我目前正在使用ArrayList并且能够遍历到第二级但不能为第三级执行。 那么这样做的最佳方式是什么?

谢谢

编辑:

我被要求仅使用基于DOS的Java应用程序构建此概念。

下面是一些示例代码,使用递归在层次结构中列出它们。 Item类有一个子列表。 诀窍是将任何新的孩子添加到正确的父母。 这是我创建的方法:

 public Item getItemWithParent(int parentID){ Item result = null; if(this.categoryID == parentID){ result = this; } else { for(Item nextChild : children){ result = nextChild.getItemWithParent(parentID); if(result != null){ break; } } } return result; } 

可能有一种更有效的方法,但这有效。

然后,当您想要向层次结构中添加新项时,请执行以下操作:

 public void addItem(int categoryID, String name, int parentID) { Item parentItem = findParent(parentID); parentItem.addChild(new Item(categoryID, name, parentID)); } private Item findParent(int parentID) { return rootNode.getItemWithParent(parentID); } 

对于实际的显示,我只是传入一个“标签级别”,它表示标签的距离,然后为每个孩子递增,如下所示:

 public String toStringHierarchy(int tabLevel){ StringBuilder builder = new StringBuilder(); for(int i = 0; i < tabLevel; i++){ builder.append("\t"); } builder.append("-" + name); builder.append("\n"); for(Item nextChild : children){ builder.append(nextChild.toStringHierarchy(tabLevel + 1)); } return builder.toString(); } 

哪个给了我这个:

 -electronics -Television -21inch -Test -23inch -LCD display -player -mp3player -vcd player -hd quality -dvd player 

你可以拥有一个受Swing TreeModel启发的设计。

编辑当我这样说时,我的意思是你可以使用一个实现类似接口的类; 注意你甚至可以直接使用这个接口,因为Swing是标准JRE的一部分,并且可以在标准Java可用的任何地方使用。

此外,因为它是一个接口(而不是一个类),它只是你构建你的调用的一种方式。 因此,您可以在基于控制台的应用程序中轻松使用它。

 public class FileReader { Map employees; Employee topEmployee; class Employee { int id; int mgrId; String empName; List subordinates; public Employee(String id, String mgrid, String empName) { try { int empId = Integer.parseInt(id); int mgrId = 0; if (!"Null".equals(mgrid)) { mgrId = Integer.parseInt(mgrid); } this.id = empId; this.mgrId = mgrId; this.empName = empName; } catch (Exception e) { System.out.println("Unable to create Employee as the data is " + id + " " + mgrid + " " + empName); } } List getSubordinates() { return subordinates; } void setSubordinates(List subordinates) { this.subordinates = subordinates; } int getId() { return id; } void setId(int id) { this.id = id; } int getMgrId() { return mgrId; } } public static void main(String[] args) throws IOException { FileReader thisClass = new FileReader(); thisClass.process(); } private void process() throws IOException { employees = new HashMap(); readDataAndCreateEmployees(); buildHierarchy(topEmployee); printSubOrdinates(topEmployee, tabLevel); } private void readDataAndCreateEmployees() throws IOException { BufferedReader reader = new BufferedReader(new java.io.FileReader("src/main/java/com/springapp/mvc/input.txt")); String line = reader.readLine(); while (line != null) { Employee employee = createEmployee(line); employees.put(employee.getId(), employee); if (employee.getMgrId() == 0) { topEmployee = employee; } line = reader.readLine(); } } int tabLevel = 0; private void printSubOrdinates(Employee topEmployee, int tabLevel) { for (int i = 0; i < tabLevel; i++) { System.out.print("\t"); } System.out.println("-" + topEmployee.empName); List subordinates = topEmployee.getSubordinates(); System.out.print(" "); for (Employee e : subordinates) { printSubOrdinates(e, tabLevel+1); } } public List findAllEmployeesByMgrId(int mgrid) { List sameMgrEmployees = new ArrayList(); for (Employee e : employees.values()) { if (e.getMgrId() == mgrid) { sameMgrEmployees.add(e); } } return sameMgrEmployees; } private void buildHierarchy(Employee topEmployee) { Employee employee = topEmployee; List employees1 = findAllEmployeesByMgrId(employee.getId()); employee.setSubordinates(employees1); if (employees1.size() == 0) { return; } for (Employee e : employees1) { buildHierarchy(e); } } private Employee createEmployee(String line) { String[] values = line.split(" "); Employee employee = null; try { if (values.length > 1) { employee = new Employee(values[0], values[2], values[1]); } } catch (Exception e) { System.out.println("Unable to create Employee as the data is " + values); } return employee; } } 

使用ArrayList作为输入,将需要递归方法来打印分层/树表示中的所有节点。

如果你没有使用递归,那么这可能是你不能达到大于第二个级别的水平,你提到的。

递归的一些链接:

http://en.wikipedia.org/wiki/Recursion

http://www.java-samples.com/showtutorial.php?tutorialid=151

为了高效,我会创建这样的东西:

 public class Node { // My name public String name; // My first child. Null if no children. public Node child; // The next child after me under the same parent. public Node sibling; // The top node in the tree. public static Node adam; // Add first node to tree public Node(String name) { this.name=name; this.child=null; this.sibling=null; adam=this; } // Add a non-Adam node to the tree. public Node(String name, Node parent) { // Copy my name. Easy part. this.name=name; // Make me the first child of my parent. The previous first child becomes // my sibling. If the previous first child was null, fine, now my sibling is null. // Note this means that children always add to the front. If this is undesirable, // we could make this section a little more complicated to impose the desired // order. this.sibling=parent.child; parent.child=this; // As a new node, I have no children. this.child=null; } // Print the current node and all nodes below it. void printFamily(int level) { // You might want a fancier print function than this, like indenting or // whatever, but I'm just trying to illustrate the principle. System.out.println(level+" "+name); // First process children, then process siblings. if (child!=null) child.printFamiliy(level+1); if (sibling!=null) sibling.printFamily(level); } // Print all nodes starting with adam static void printFamily() { adam.printFamily(1); } // Find a node with a given name. Must traverse the tree. public static Node findByName(String name) { return adam.findByName(name); } private Node findByNameFromHere(String name) { if (this.name.equals(name)) return this; if (child!=null) { Node found=child.findByNameFromHere(name); if (found!=null) return found; } if (sibling!=null) { Node found=sibling.findByNameFromHere(name); if (found!=null) return found; } return null; } // Now we can add by name public Node(String name, String parentName) { super(name, findByName(parentName)); } } 

通常免责声明:此代码不在我的头顶,完全未经测试。

如果我是为一个真正的应用程序做这个,我会包括错误检查,毫无疑问是各种各样的外围设备。