用给定的顺序构造一个二叉树

时间:2018-11-12 15:15:58

标签: java algorithm data-structures

我正在尝试使用给定preorder构建二叉树。

我的方法是遍历数组并检查每个元素。如果该元素是运算符(+, -, *, /),那么我将当前元素设置为root,并将root.leftroot.right分别设置为array[i + 1]array[i + 2]

如果当前元素不是运算符,我将打印出该元素。

我认为,如果我递归执行此操作,则可以构造一个二叉树。但是,我遇到了一些错误,不确定是否要朝正确的方向前进。

到目前为止,这是我的代码:

class Node {
    Object data;
    Node left, right;

    Node(Object item) {
        data = item;
        left = right = null;
    }
}

public class MyTree {
    Node root;

    public MyTree() {
        root = null;
    }

    private static String[] array;
    private static MyTree01 tree = new MyTree();

    static void createBT(Node node) {

        if (array == null) return;

        for (int i = 0; i < array.length; i++) {
            if (array[i] == "-" || array[i] == "+" || array[i] == "*" || array[i] == "/") {
                tree.root = new Node(array[i]);
                tree.root.left = new Node(array[i + 1]);
                tree.root.right = new Node(array[i + 2]);

                createBT(tree.root.left);
                createBT(tree.root.right);

            } else {
                System.out.println(node.data + " ");
            }
        }
    }

    void createBT() {
        createBT(root);
    }

    public static void main(String[] args) {
        array = new String[] {"-", "-", "x", "y", "*", "+", "s", "t", "/", "x", "s"};
        createBT(tree.root);
    }
}

同样,我不确定我是否朝着正确的方向前进。我需要一些指导,如果我的方法完全错误,请告诉我!

1 个答案:

答案 0 :(得分:1)

import java.util.*;
class Node {
    String data;
    Node left, right;

    Node(String item) {
        data = item;
        left = right = null;
    }
}
public class Algo{   
    public Node createBT(String[] arr){
       Node root = null;
       if(arr == null || arr.length == 0) return root;// to handle edge case of empty lists.
       Stack<Node> st = new Stack<>();

       for(int i=0;i<arr.length;++i){
            Node new_node = new Node(arr[i]);
            attachChildToParent(st,new_node);// attach child to it's parent(which will be most recent/top in the stack)
            if(root == null) root = new_node;
            if(isOperator(arr[i])){                                                  
                st.push(new_node); // only push operators to stack as operands will always be leaf nodes
            }
       }

       return root;
    }    

    private boolean isOperator(String s){
        return s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/");
    }

    private void attachChildToParent(Stack<Node> st,Node child_node){
        if(st.isEmpty()) return;
        Node parent_node = st.peek();
        if(parent_node.left == null){
            parent_node.left = child_node;
        }else{
            parent_node.right = child_node;
            st.pop(); // no need to keep parent in the stack anymore since we assigned nodes on both ends(left and right) 
        }
    }

    private void preorder(Node root,List<String> nodes){
        if(root == null) return;
        nodes.add(root.data);
        preorder(root.left,nodes);
        preorder(root.right,nodes);        
    }

    public static void main(String[] args) {
        String[][] test_cases = new String[][]{
            {"-", "-", "x", "y", "*", "+", "s", "t", "/", "x", "s"},
            {"/","-", "-", "x", "y", "*", "+", "s", "t", "/", "x", "s","t"},
            {"y"}
        };        
        Algo obj = new Algo();
        for(int i=0;i<test_cases.length;++i){
            Node root = obj.createBT(test_cases[i]);
            List<String> preorder_result = new ArrayList<>();
            obj.preorder(root,preorder_result);
            boolean expected_success = true;
            for(int j=0;j<test_cases[i].length;++j){
                if(!test_cases[i][j].equals(preorder_result.get(j))){
                    expected_success = false;
                    break;
                }                
            }
            System.out.println("Test Case: " + Arrays.toString(test_cases[i]));
            if(expected_success){
                System.out.println("Result: ok");
            }else{
                System.out.println("Result: not ok");
            }
        }

    }
}

输出:

Test Case: [-, -, x, y, *, +, s, t, /, x, s]
Result: ok
Test Case: [/, -, -, x, y, *, +, s, t, /, x, s, t]
Result: ok
Test Case: [y]
Result: ok 

说明:

  • 了解操作数(变量)将始终是叶节点。树的根节点也可以是叶节点(在整个表达式中只有1个操作数时会发生变化)。

  • 现在,由于您提到了BT的预购遍历,因此我们采用从左至上的方法,并使用堆栈 >创建我们的二叉树。

  • 无论何时,只要我们看到一个操作数(+,-,*,/),我们(显然)就会创建一个新节点并将其压入堆栈。之所以要推送它,是因为要使整个表达式有意义,我们仍然需要收集它的正确子树(该子树将出现在数组的未来值中)。

  • 通过从左至先的方法,我的意思是,我们从堆栈中获取当前节点的父节点(如果不为空),并检查其左子树是否为空,如果是的,在那里分配孩子,否则将其分配到右边。我们这样做是因为给您的遍历是预订

  • 如果new_nodeoperator,我们将其再次推入堆栈,以容纳将来作为叶节点的变量。例如,{"-,"-","x","y"}。因此,它的树看起来像

        -
       /  
      -
     / \
    x   y
    
  • 在上面的表达式中,y被分配给其父项-,然后我们从堆栈中删除了最新的-,因为我们不再需要它了。 p>

  • 现在,堆栈中剩下的只是-,它是根节点。然后,我们继续移至数组中的其他值,并如上所述确定它们。