如何将平面数据结构显示为分层数据结构(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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:53:51  来源:igfitidea点击:

How to display flat data structure into hierarchical data structure (Java)?

javadata-structures

提问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

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

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

回答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.

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