我正在尝试使用给定preorder
的仅构建二叉树。
我的方法是遍历数组并检查每个元素。如果该元素是运算符(+, -, *, /)
,那么我将当前元素设置为root,并将root.left
和root.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);
}
}
同样,我不确定我是否朝着正确的方向前进。我需要一些指导,如果我的方法完全错误,请告诉我!
答案 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_node
是operator
,我们将其再次推入堆栈,以容纳将来作为叶节点的变量。例如,{"-,"-","x","y"}
。因此,它的树看起来像
-
/
-
/ \
x y
在上面的表达式中,y
被分配给其父项-
,然后我们从堆栈中删除了最新的-
,因为我们不再需要它了。
现在,堆栈中剩下的只是-
,它是根节点。然后,我们继续移至数组中的其他值,并如上所述确定它们。