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

如何将平面数据结构显示为层次数据结构(Java)?,java,data-structures,Java,Data Structures,我最近在一次求职考试中遇到了这个问题 假设您有一个平面数据结构,如下所示: **Category** **Name** **Parent** 1 electronics 0 2 Television 1 3 21inch 2 4 23inch

我最近在一次求职考试中遇到了这个问题

假设您有一个平面数据结构,如下所示:

**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
然后它应该在
21英寸
下方显示
Test
条目

所以对于这类事情,我目前使用的是
ArrayList
,能够遍历到第二级,但无法遍历到第三级。那么,做这件事的最佳方式是什么呢

谢谢

编辑:


我被要求只使用基于DOS的Java应用程序来构建这个概念

你可以从Swing中得到灵感

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


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

使用ArrayList作为输入,需要使用递归方法以分层/树表示形式打印所有节点

如果您没有使用递归,那么这可能是您无法达到高于您提到的第二个级别的原因

有关递归的一些链接:


以下是一些示例代码,使用递归将它们按层次结构列出。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();
}
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));
  }
}
对于实际显示,我只需传入一个“tab level”,它表示要在多大程度上进行tab,然后为每个子级递增它,如下所示:

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();
}
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));
  }
}

为了提高效率,我会创建如下内容:

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();
}
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));
  }
}
通常的免责声明:这段代码是从我的头上掉下来的,完全没有经过测试

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

公共类文件阅读器{
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;
    }
}
地图员工; 员工至上员工; 班级员工{ int-id; 总经理; 字符串名称; 列出下属; 公共雇员(字符串id、字符串mgrid、字符串empName){ 试一试{ int empId=Integer.parseInt(id); int-mgrId=0; 如果(!“Null”。等于(mgrid)){ mgrId=Integer.parseInt(mgrId); } this.id=empId; this.mgrId=mgrId; this.empName=empName; }捕获(例外e){ System.out.println(“无法创建员工,因为数据为”+id+“”+mgrid+“”+empName); } } 列出下属(){ 回报下属; } 作废集合坐标(列出下级){ 这个。下属=下属; } int getId(){ 返回id; } void setId(int id){ this.id=id; } int getMgrId(){ 返回mgrId; } } 公共静态void main(字符串[]args)引发IOException{ FileReader thisClass=新建FileReader(); thisClass.process(); } 私有void进程()引发IOException{ employees=newhashmap(); readDataAndCreateEmployees(); 构建层次结构(topEmployee); 打印下属(topEmployee,tabLevel); } 私有void readDataAndCreateEmployees()引发IOException{ BufferedReader=new BufferedReader(new java.io.FileReader(“src/main/java/com/springapp/mvc/input.txt”); 字符串行=reader.readLine(); while(行!=null){ Employee=createEmployee(行); employee.put(employee.getId(),employee); if(employee.getMgrId()==0){ topEmployee=员工; } line=reader.readLine(); } } int tabLevel=0; 私人下属(员工topEmployee,int tabLevel){ for(int i=0;i1){ 员工=新员工(值[0]、值[2]、值[1]); } }捕获(例外e){ System.out.println(“无法创建员工,因为数据为”+值); } 返回员工; } }
如果你能放一些代码片段,我就能理解你的代码,那就太好了