如何将平面数据结构显示为分层数据结构(Java)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3228334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to display flat data structure into hierarchical data structure (Java)?
提问by harshalb
I have recently faced this question in a practical test for a job .
我最近在工作的实际测试中遇到了这个问题。
Suppose you are given a flat data structure like this :
假设你有一个像这样的平面数据结构:
**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
Now from the above flat data structure we want to show something like the below hierarchical tree structure .
现在从上面的平面数据结构中,我们想要展示类似于下面的分层树结构。
-Electronics
| -Television
| | -21 inch
| | -23 inch
| | -lcd display
| -Player
| | -mp3player
| | -vcdplayer
| | | -HD display
| | -DVD player
Then If I am adding another entry to my array like :
然后,如果我将另一个条目添加到我的数组中,例如:
11 Test 3
then it should show Testentry just below 21inch.
那么它应该Test在下面显示条目21inch。
So for this sort of thing I am currently using ArrayListand have been able to traverse till second level but can't do so for third level . So what is the perfect way for doing this ?
因此,对于我目前正在使用的这种东西ArrayList,并且已经能够遍历到第二级,但对于第三级却不能这样做。那么这样做的完美方法是什么?
Thanks
谢谢
EDIT :
编辑 :
I was asked to build this concept using DOS based Java application only.
我被要求只使用基于 DOS 的 Java 应用程序来构建这个概念。
采纳答案by Matt N
Here is some sample code that lists them in a hierarchy using recursion. The Item class has a List of children. The trick is adding any new children to the right parent. Here is the method I created to do this:
下面是一些示例代码,使用递归在层次结构中列出它们。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;
}
There is probably a more efficient way, but this works.
可能有一种更有效的方法,但这是有效的。
Then, when you want to add new items to your hierarchy, do something like this:
然后,当您想向层次结构添加新项目时,请执行以下操作:
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);
}
For the actual display, I just pass in a "tab level" that says how far to tab in, then increment it for each child like this:
对于实际显示,我只是传入一个“标签级别”,说明标签的距离,然后为每个孩子增加它,如下所示:
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();
}
Which gives me this:
这给了我这个:
-electronics
-Television
-21inch
-Test
-23inch
-LCD display
-player
-mp3player
-vcd player
-hd quality
-dvd player
回答by Riduidel
You could have a design inspired by Swing TreeModel.
你可以有一个受 Swing TreeModel启发的设计。
EDITWhen I say that, I mean you could use a class implementing a likewise interface; Noticeyou can even go as far as using directly this interface, as Swing is a part of standard JRE and is available everywhere standard Java is avaiable.
编辑当我这么说时,我的意思是你可以使用一个实现类似接口的类;请注意,您甚至可以直接使用此接口,因为 Swing 是标准 JRE 的一部分,并且在标准 Java 可用的任何地方都可用。
Furthermore, as it is an interface (and not a class), it's only a way for you to structure your calls. As a consequence, you can easily use it in a console based application.
此外,由于它是一个接口(而不是一个类),它只是您构建调用的一种方式。因此,您可以轻松地在基于控制台的应用程序中使用它。
回答by Pramod
public class FileReader {
Map<Integer, Employee> employees;
Employee topEmployee;
class Employee {
int id;
int mgrId;
String empName;
List<Employee> 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<Employee> getSubordinates() {
return subordinates;
}
void setSubordinates(List<Employee> 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<Integer, Employee>();
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<Employee> subordinates = topEmployee.getSubordinates();
System.out.print(" ");
for (Employee e : subordinates) {
printSubOrdinates(e, tabLevel+1);
}
}
public List<Employee> findAllEmployeesByMgrId(int mgrid) {
List<Employee> sameMgrEmployees = new ArrayList<Employee>();
for (Employee e : employees.values()) {
if (e.getMgrId() == mgrid) {
sameMgrEmployees.add(e);
}
}
return sameMgrEmployees;
}
private void buildHierarchy(Employee topEmployee) {
Employee employee = topEmployee;
List<Employee> 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;
}
}
回答by Andreas
Using your ArrayList as input a recursive method will be needed to print all nodes in a hierarchical/tree representation.
使用您的 ArrayList 作为输入,将需要递归方法以分层/树表示形式打印所有节点。
If you are not using recursion then this might be the reason that you cannot go to levels greater than the second one, that you mention.
如果您不使用递归,那么这可能是您无法进入高于您提到的第二个级别的原因。
Some links on recursion:
关于递归的一些链接:
http://en.wikipedia.org/wiki/Recursion
http://en.wikipedia.org/wiki/Recursion
回答by Jay
To be efficient, I'd create something like this:
为了提高效率,我会创建这样的东西:
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));
}
}
Usual disclaimer: This code is off the top of my head, completely untested.
通常的免责声明:此代码超出了我的脑海,完全未经测试。
If I was doing this for a real application, I would include error checking and no doubt all sorts of peripheral stuff.
如果我是为一个真正的应用程序这样做,我会包括错误检查和毫无疑问的各种外围设备。

