Java递归和二叉树

时间:2016-03-31 18:15:56

标签: java recursion tree binary-tree

我的课程一直致力于使用递归来创建像河内的塔,斐波纳契以及所有有趣的东西。问题是,我并不是很了解一切。我理解递归的一般概念,但在制作程序时将其付诸实践对我来说感觉很复杂。我知道它一遍又一遍地调用这个方法,通常会在它退出的情况下达到一个基本情况,但是我很难编写能够做我想做的事情的代码。

我们正在研究二叉树。我们应该使用我教授提供的一些代码来分割树,然后编写一个递归方法来打印出树所包含的所有路径。我们的输入将类似(a(b()())(c()())),它将是一棵树:

 a
b c

b和c下面会有0个孩子。 (a)是一个可能的节点,()将是一个空节点,它将是该路径的结尾。我们的目标是打印出所有路径,因此对于我的示例,输出将是:

a b

a c

我们给出的代码包含一个帮助器方法,我们可以用它来编写递归方法:

public class BinaryTree {


public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String tree = scan.nextLine();//correct format : (a()())
    String[] t = splitTree(tree);
    System.out.println(Arrays.toString(t));

}
public static String[] splitTree(String tree)
{
    //expected format
    //(node tree tree)
    //0 1 2-x x-(length-2) length-1
    if(tree.length() <= 2)//tree not long enough to process
        return new String[]{tree};

    String[] temp = new String[3];
    temp[0] = "" + tree.charAt(1);//grab tree node
    tree = tree.substring(2, tree.length()-1);//remove node and outer paren
    int parenCount = 0;//count of open paren
    int endTreeOne = 0;//end of first tree
    for(int i = 0; i < tree.length(); i++)
    {
        if(tree.charAt(i) == '(')
            parenCount++;
        if(tree.charAt(i) == ')')
            parenCount--;
        if(parenCount == 0)
        {
            endTreeOne = i;
            break;//ends for loop early
        }
    }
    temp[1] = tree.substring(0, endTreeOne+1);//left tree
    temp[2] = tree.substring(endTreeOne+1);//right tree
    return temp;
}

此方法基本上会转换(a(b()())(c()()))之类的字符串,并使它们成为[a, (b()()), (c()())]。基本上拆分树。

我真的不确定如何从这里开始编写我的递归方法。我觉得自己很丢失(结果很沮丧)。我想我需要让我的方法检查是否存在“()”,那么这就是路径的结束。这是退出我需要的循环的基本情况吗?我不知道如何指定树的哪一侧也可以。如果有人可以提供任何帮助,提示或让我按照正确的思路解决这个问题,我将非常感激。

1 个答案:

答案 0 :(得分:1)

我觉得“打印路径”步骤对于树的对象会更容易,所以让我们来定义它。

以递归方式实现toString方法,以重新打印要解析到此对象的内容。

public class BinaryTreeNode {
    public String root;
    public BinaryTreeNode left;
    public BinaryTreeNode right;

    public BinaryTreeNode(String root) {
        this.root = root;
    }

    @Override
    public String toString() {
        String s = root;

        if (left != null) {
            s += left.toString();
        } else {
            s += "()";
        }

        if (right != null) {
            s += right.toString();
        } else {
            s += "()";
        }

        return "(" + s + ")";
    }
}

我还有一个辅助方法来计算括号,如果有任何不匹配则抛出错误。

private static int getParenCount(String s) {
    int parenCount = 0;
    int opened = 0;

    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c == '(') {
            parenCount++;
            opened++;
        } else if (c == ')') {
            parenCount++;
            opened--;
        }
    }
    if (opened != 0) {
        throw new IllegalArgumentException("Paren mismatch." + s + " is not a valid tree.");
    }
    return parenCount;
}

然后,关于解析字符串,我留下了一些有用的代码注释。

public static BinaryTreeNode getTree(String treeString) {
    // Initialize variables
    String root;
    String leftTree;
    String rightTree;
    BinaryTreeNode tree = new BinaryTreeNode("");

    System.out.println("Input: " + treeString);

    if (treeString.equals("()")) {
        System.out.println("Empty tree. Returning!");
        return null;
    }

    // Check for even parenthesis
    int parenCount = getParenCount(treeString);
    if (parenCount % 2 == 0) {

        // Strip the outside parenthesis
        treeString = treeString.substring(1, treeString.length()-1);
        System.out.println("tree: " + treeString);

        // Find the first '(' because the root is everything before it
        int leftTreeStart = treeString.indexOf('(');
        root = treeString.substring(0, leftTreeStart);

        // Find the complete left-tree
        int leftTreeEnd = leftTreeStart + 1;
        int leftTreeParenCount = 0;
        for (int i = leftTreeStart-1; i < treeString.length(); i++) {
            char c = treeString.charAt(i);
            if (c == '(') {
                leftTreeParenCount++;
            } else if (c == ')') {
                leftTreeParenCount--;
                if (leftTreeParenCount == 0) {
                    leftTreeEnd = i;
                    break;
                }
            }
        }

        System.out.println("root: " + root);
        tree.root = root;

        leftTree = treeString.substring(leftTreeStart, leftTreeEnd + 1);
        System.out.println("\nleft: " + leftTree);
        System.out.println("Recurse left...");
        tree.left = getTree(leftTree); // recurse here

        // The right-tree is just the remainder of the string
        rightTree = treeString.substring(leftTreeEnd + 1);
        System.out.println("\nright:" + rightTree);
        System.out.println("Recurse right...");
        tree.right = getTree(rightTree); // recurse here

    }

    return tree; 
}