以特定深度递归创建二叉树

时间:2015-08-03 17:22:08

标签: java recursion tree binary-tree

我想创建一个具有特定深度的二叉树。 到目前为止,我的代码创建二叉树直到特定的最大深度,但也创建了具有较低最大深度的树。我将在下面说明我的问题。

到目前为止我的代码(方法称为term = Literal('True') | 'False' | '$' | quotedString.setParseAction(removeQuotes) expr = infixNotation(term, [ ('~', 1, opAssoc.RIGHT), (oneOf('-> <->'), 2, opAssoc.LEFT), ('&', 2, opAssoc.LEFT), ('|', 2, opAssoc.LEFT), ]) ):

create

问题: 如果我输入3作为深度,它应该创建像 ONLY

这样的树
public class BT<E>{
   E value;
   BT<E> left, right;

   public BT(E value)
   {
      this.value=value;
   }   

   public BT (E value, BT left, BT right) 
   {
      this.value = value;
      this.left = left;
      this.right = right;
   }

   private static final String[] random = {"a","b","c","d"};
   public static BT create(int depth) {
      if (depth > 1 && random.nextBoolean())//if not at the maximum depth
      //choose randomly a,b,c,d - nextBoolean ensures it is not balanced all the time
      {
         String random = OPERATORS[random.nextInt(OPERATORS.length)];
         return new BT(operator, create(depth-1), create(depth-1));//recursively create tree
      } 
      else {//when node is a leaf node, make it X
         String t = "x";
         return new BT(t);
      }
   }
}

我的代码当前创建了如上所述的树,但也包括如下树:

    (c)              (d)         (a)
 (b)   (a)         (b)        (d)   (c)
(x)(x)(x)(x)     (x)  (x)             (x)

显然这些不是深度3.我不想要这个。我希望前者没有这些例外。

有人可以查看我的代码并告诉我我做错了什么以及如何纠正它。

3 个答案:

答案 0 :(得分:3)

最简单的方法是创建一个调用create树函数的包装函数。

该函数将使用您的函数随机自由创建,测试它是否具有所需的深度X长度。如果是,它将返回;如果没有,它将再次调用你的函数,直到它找到一个深度正确的树

答案 1 :(得分:0)

问题是:

  

random.nextBoolean()

在这一行:

if (depth > 1 && random.nextBoolean())

您打算使用此语句创建不平衡树,但这也很有可能在没有任何最大深度分支的情况下创建树。您只需要在递归的早期连续几次返回 false ,就会产生不良结果。鉴于有50%的机会发生这种情况,它会发生比你想象的更多!要保证至少一个具有最大深度的分支,您需要更多的处理。

一个建议可能是预先确定树中将达到最大深度的一个或多个分支,并让其他分支机会成为可能。当您使用二叉树时,可以使用布尔值来完成:

int depth = 3;
boolean[] branch = new boolean[depth];
for (int i = 0; i < branch.length; i++) {
  branch[i] = random.nextBoolean();
}

一旦你有了这个,就像现在一样生成你的树。完成后,按照boolean []的说明在树中移动,使用左侧为true,右侧为false。如果您发现特定布尔值缺少子节点,并且您没有达到最大深度,请创建该子节点并继续。这不是一种特别有吸引力的方式,但它便宜又快捷。

一旦这项工作正常,您可以添加更多复杂性 - 更多保证分支,以及来自这些分支的其他分支 - 以便充实树。随着您的最大深度增加,降低结束分支的机会可能是明智的,否则您将最终得到一个长的最大深度分支和较小的分支。

答案 2 :(得分:0)

如前所述,问题出现在这一行:

if (depth > 1 && random.nextBoolean())

你要做的是:

  • 控制评估顺序:

    考虑return new BT(operator, create(depth-1), create(depth-1));

    将始终首先评估左侧树,然后评估右侧树。

  • 如果其中一个树已达到所需深度,则让树木创建叶子:

    我为此创建了一个布尔变量finished

首先,我们将创建一个具有所需深度的路径。然后我们将让其他路径创建一个Tree或Leaf。

    private boolean finished;

    public BT<E> create(int depth){
        if(depth<=0) { // One tree is at desired depth
            finished = true;
            return new BT<E>(null);
        }
        if(finished) // Let the other trees set a Leaf.
            if(random.nextBoolean())
                return new BT<E>(null);

        BT<E> temp = create(depth-1); // Control evaluation
        if (random.nextBoolean()) // evaluate left and right evenly distributed
            return new BT<E>(null, temp, create(depth-1));
        else return new BT<E>(null, create(depth-1), temp);

请注意,由于

,创建的树将比稀疏更稀疏
if(finished)
    if(random.nextBoolean())
        return new BT<E>(null);

您可能希望使随机变量取决于当前路径的数量。