我的课程一直致力于使用递归来创建像河内的塔,斐波纳契以及所有有趣的东西。问题是,我并不是很了解一切。我理解递归的一般概念,但在制作程序时将其付诸实践对我来说感觉很复杂。我知道它一遍又一遍地调用这个方法,通常会在它退出的情况下达到一个基本情况,但是我很难编写能够做我想做的事情的代码。
我们正在研究二叉树。我们应该使用我教授提供的一些代码来分割树,然后编写一个递归方法来打印出树所包含的所有路径。我们的输入将类似(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()())]
。基本上拆分树。
我真的不确定如何从这里开始编写我的递归方法。我觉得自己很丢失(结果很沮丧)。我想我需要让我的方法检查是否存在“()”,那么这就是路径的结束。这是退出我需要的循环的基本情况吗?我不知道如何指定树的哪一侧也可以。如果有人可以提供任何帮助,提示或让我按照正确的思路解决这个问题,我将非常感激。
答案 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;
}