簡體   English   中英

如何將平面數據結構顯示為分層數據結構(Java)?

[英]How to display flat data structure into hierarchical data structure (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
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;
    }
}

你可以擁有一個受Swing TreeModel啟發的設計。

編輯當我這樣說時,我的意思是你可以使用一個實現類似接口的類; 注意,您甚至可以直接使用此接口,因為Swing是標准JRE的一部分,並且可以在標准Java可用的任何地方使用。

此外,因為它是一個界面(而不是一個類),它只是你構建你的調用的一種方式。 因此,您可以在基於控制台的應用程序中輕松使用它。

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

通常免責聲明:此代碼不在我的頭頂,完全未經測試。

如果我這樣做是為了一個真正的應用程序,我會包括錯誤檢查,毫無疑問是各種各樣的外圍設備。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM