简体   繁体   English

预订遍历树

[英]Pre-Order Traversal Tree

I seem to be having an issue adding right nodes to left nodes. 我似乎在向左节点添加正确的节点时遇到问题。 I have an input file (.txt) that is listed in pre-order 我有一个预订中列出的输入文件(.txt)

Fred    1900
2
John    1925
3
Mary    1950
2
Jason   1972
0
Heather 1975
2
Sydney  2002
0
Hailey  2005
0
John    1951
1
Amy 1983
0
Fred    1953
3
Mark    1977
0
Sarah   1979
1
Michael 2005
0
Adam    1982
0
Joan    1927
2
Susan   1949
0
David   1952
1
Fred    1980
0

Here is my Node class: 这是我的Node类:

public class Node {
    public String name;
    public int year;
    //this will help with determining the parent in the insertion process
    public int children;    
    public Node parent;
    public Node left;
    public Node right;


    public Node(String name, int year, int children){
        this.name = name;
        this.year = year;
        this.children = children;
    }
}

Assuming that my nodes are created successfully I seem to be having an issue creating the actual tree. 假设我的节点成功创建,我似乎在创建实际树时遇到问题。

public class FamilyTree {    

    public Node familyTree;

    private Node pivotalNode;
    private Node parent;
    private int children = 0;
    //This method adds a family member to the family tree    
    public void add(Node newNode){
        familyTree = add(familyTree,newNode);
    }
    private Node add(Node familyTree, Node newNode){        
        if(familyTree == null){
            children = newNode.children;
            newNode.parent = parent;
            familyTree = newNode;

        }
        else if(children > 0){
            parent = familyTree;
            familyTree.left = add(familyTree.left, newNode);
            pivotalNode = familyTree.left;
        }
        else if(children == 0){          

            familyTree.right = add(familyTree.right, newNode);
            return pivotalNode;
        }        
        return familyTree;
    }  
} 

The Results are to show a Tree as follows: 结果将显示树如下: 在此输入图像描述

Here is my Main method: 这是我的主要方法:

public class Operations {

    //Not necessary but it helps me to get more organized. Just want to extract information first.
    public static ArrayList<String> information = new ArrayList<String>();  

    public static void main(String args[]){
        //extract information from file
        getFileContents();

        //Object initialization
        FamilyTree family = new FamilyTree();

        //some useful variables for loop below
        int children =0;
        String[] splitted = null;
        Node member = null;        

        for(int i=0; i<information.size(); i++){
            //Every other line in the text file perform a different operation
            if(i % 2 == 1){
                try{
                    children = Integer.parseInt(information.get(i));
                    member = new Node(splitted[0], Integer.parseInt(splitted[1]), children);
                    family.add(member);
                }
                catch(Exception e){
                    //this determines if the pattern is broken
                    break;
                }
            }
            if(i % 2 == 0){                               
                splitted = information.get(i).split("\\s+");
                //this determines a pattern difference                
                if(splitted.length < 2){
                    break;
                }
            }
        }
        System.out.print("hi");
    }
    //Pretty self explanatory. Read each line of the file and store it into an array. 
    //Not necessary as everything could technically be done at once (insertion), but this keeps me 
    //more organized to put everything together later on 
    public static void getFileContents(){
        try{
            BufferedReader br = new BufferedReader(new FileReader("includes\\assn2in.txt"));            

            String line;
            String info;

            while ((line = br.readLine()) != null) {
                info = line.replaceAll("\\s+", " ");
                information.add(info);               
            }            
            br.close();


        }
        catch(IOException e){
            System.out.println("Error: "+e);
        }
    } 
}

Any help would be appreciated thanks. 任何帮助将不胜感激。

One big issue you have is that your Node class models a binary tree structure--that is, it contains left and right members to represent the children--but the data itself does not conform to this structure. 你有一个很大的问题是,你的Node级车型的二叉树结构-也就是说,它包含leftright会员代表孩子-但数据本身并不符合这个结构。 If you look at the diagram, you can see that some nodes have as many as three children (eg John 1925 and Fred 1953). 如果查看图表,您可以看到一些节点有多达三个子节点(例如John 1925和Fred 1953)。 You need to use an ArrayList instead of left and right so that your Node can handle an arbitrary number of children: 您需要使用一个ArrayList ,而不是leftright ,使您的Node可以处理孩子任意数量的:

public class Node {
    public String name;
    public int year;
    //this will help with determining the parent in the insertion process
    public int expectedNumberOfChildren;    
    public Node parent;
    public ArrayList<Node> children;

    public Node(String name, int year, int expectedNumberOfChildren){
        this.name = name;
        this.year = year;
        this.expectedNumberOfChildren = expectedNumberOfChildren;
        this.children = new ArrayList<Node>(expectedNumberOfChildren);
    }
}

As far as building the tree from the data file, I would use a Stack structure with the following algorithm (pseudocode): 至于从数据文件构建树,我将使用具有以下算法的Stack结构(伪代码):

  • Create an empty stack. 创建一个空堆栈。
  • Initialize a Node variable called "root" to null. 将名为“root”的Node变量初始化为null。
  • Open the data file for reading. 打开数据文件进行读取。
  • While not at the end of the file: 虽然不在文件的末尾:
    • Read the next name, year and expected number of children from the file. 从文件中读取下一个名称,年份和预期的子项数。
    • Create a new Node from the name, year and expected number of children. 根据名称,年份和预期的子项数创建新节点。
    • If the root node is null: 如果根节点为null:
      • Set the root node to the new node. 将根节点设置为新节点。
      • Push the new node onto the stack. 将新节点推入堆栈。
    • Otherwise: 除此以外:
      • Pop the last node off the stack (call this "parent"). 从堆栈中弹出最后一个节点(称为“父”)。
      • Set the new node's parent to the parent just popped off the stack. 将新节点的父节点设置为刚刚从堆栈弹出的父节点。
      • Add the new node to the parent's list of children. 将新节点添加到父级的子级列表中。
      • If the actual size of the parent's list of children is less than the parent's expected number of children originally read from the file, push the parent back onto the stack. 如果父级子级列表的实际大小小于父级最初从该文件中读取的子级的预期子级数,则将父级推回到堆栈中。
      • If the expected number of children of the new node is greater than zero, push it onto the stack. 如果新节点的预期子节点数大于零,则将其推入堆栈。
  • Close the file. 关闭文件。

And that's it. 就是这样。 When the loop finishes, the "root" node will point to the fully-constructed tree, assuming the input file is well-formed. 当循环结束时,假设输入文件格式正确,“根”节点将指向完全构造的树。 (The stack is no longer needed after that.) (之后不再需要堆栈。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM