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

时间:2010-07-12 12:07:15

标签: java data-structures

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

假设您获得了如下平面数据结构:

**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

然后它应该在Test下面显示21inch条目。

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

谢谢

编辑:

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

5 个答案:

答案 0 :(得分:10)

以下是一些使用递归在层次结构中列出它们的示例代码。 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

答案 1 :(得分:2)

你的设计灵感来自Swing TreeModel

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

递归的一些链接:

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

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

答案 4 :(得分:1)

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

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

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

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