计算Leaf图中的节点数

时间:2016-02-09 18:02:19

标签: java data-structures binary-search-tree

在没有运气的情况下一直在努力。希望有人可以指出正确的方向。

代码:

public class BST {
  public BTNode<Integer> root;
  int nonLeafCount = 0;
  int depthCount = 0;

  public BST() {
    root = null;
  }



  class BTNode<T> {
    T data;
    BTNode<T> left, right;

    BTNode(T o) {
      data = o;
      left = right = null;
    }

    public String toString() {
      return String.valueOf(data);
    }
  }
}

2 个答案:

答案 0 :(得分:1)

在没有递归调用的情况下遍历树的简单方法是使用堆栈。将根写入堆栈,然后输入一个循环 - 只要堆栈不为空 - 从堆栈中弹出一个节点并推送该节点的非空子节点。很明显,这最终会将每个节点推送到堆栈上一次,然后只弹出一次。现在您需要做的就是计算至少有一个子节点的弹出节点。把它放在一起,

public int nonleaves() {
  int nonLeafCount = 0;
  BTNode<Integer> [] stack = new BTNode[2];
  int p = 0;
  stack[p++] = root; // push root
  while (p != 0) {
    BTNode<Integer> node = stack[--p]; // pop
    if (node.left != null || node.right != null) ++nonLeafCount;
    if (p + 1 >= stack.length) stack = Arrays.copyOf(stack, 2 * stack.length);
    if (node.right != null) stack[p++] = node.right; // push right
    if (node.left != null) stack[p++] = node.left;   // push left
  }
  return nonLeafCount;
}

请注意,根据您的描述,我使用了一个简单的Java数组作为堆栈,每当它填满时,它就会增长2倍。整数p是堆栈指针。

此外,此代码假定root为非null。如果root可以为null,则在开头添加一个检查,并在这种情况下返回0.

注意,虽然以遍历期间更改树为代价,但是通过多种方法甚至可以在没有堆栈的情况下进行遍历。 (当遍历完成时,它恢复原状。)最好的IMO是Morris's algorithm,但它们都比堆栈复杂得多。因为你似乎是一个新的程序员,所以先找出堆栈方法。

修改

找到最大深度:

public int maxDepth() {
  int max = 0;
  Pair<Integer> [] stack = new Pair[2];
  int p = 0;
  stack[p++] = new Pair(root, 1);
  while (p != 0) {
    Pair<Integer> pair = stack[--p];
    if (pair.depth > max) max = pair.depth;
    if (p + 1 >= stack.length) stack = Arrays.copyOf(stack, 2 * stack.length);
    if (pair.node.right != null) 
      stack[p++] = new Pair(pair.node.right, 1 + pair.depth);
    if (pair.node.left != null) 
      stack[p++] = new Pair(pair.node.left, 1 + pair.depth);
  }
  return max;
}

private static class Pair<T> {
  BTNode<T> node;
  int depth;
  Pair(BTNode<T> node, int depth) {
    this.node = node;
    this.depth = depth;
  }
}

最后,如果我没有指出我们可以对算法做一些代数来消除一些微小的低效率,那将是我的疏忽。您会注意到,在将左子项推入堆栈后,肯定会在下一次循环迭代中弹出。根推/弹出类似。我们也可以直接设置node。此外,还有一些冗余的比较。这个细节对于这个注释来说太多了,但这里有一个重新设计的非叶计数器(未经测试但应该工作正常):

public int nonleaves() {
  int nonLeafCount = 0;
  BTNode<Integer>[] stack = new BTNode[1];
  int p = 0;
  BTNode<Integer> node = root;
  for (;;) {
    if (node.left == null) {
      if (node.right == null) {
        if (p == 0) break;
        node = stack[--p];
      } else { // node.right != null
        ++nonLeafCount;
        node = node.right;
      }
    } else { // node.left != null
      ++nonLeafCount;
      if (node.right != null) {
        if (p >= stack.length) {
          stack = Arrays.copyOf(stack, 2 * stack.length);
        }
        stack[p++] = node.right;
      }
      node = node.left;
    }
  }
  return nonLeafCount;
}

你可以看到,为了获得一点点效率,我们失去了很多简单性。这几乎总是一个糟糕的讨价还价。我建议不要这样做。

答案 1 :(得分:0)

可能的解决方案:

public class BST<T> {
    public BTNode<T> root;
    int depthCount = 0;

    public BST() {
        root = null;
    }

    public int nonleaves() { // Method must be declared like this. No
                                // parameters.
        BTNode<T> current = root;
        BTNode<T> previous = null;
        int nonLeafCount = 0;

        while (current != null) {
            if (previous == current.parent) { // this includes when parent is
                                                // null, i.e. current is the
                                                // root.
                previous = current;
                if (current.left != null) {
                    nonLeafCount++;
                    current = current.left;
                } else if (current.right != null) {
                    nonLeafCount++;
                    current = current.right;
                } else {
                    current = current.parent;
                }
            } else if (previous == current.left) {
                previous = current;
                if (current.right != null) {
                    current = current.right;
                } else {
                    current = current.parent;
                }
            } else {
                // previous==current.right
                previous = current;
                current = current.parent;
            }
        }
        return nonLeafCount;
    }

    private static class BTNode<T> {
        BTNode<T> left, right, parent;

        /* ... */
    }
}

使用堆栈:

public class BST2<T> {
    public BTNode<T> root;
    int depthCount = 0;

    public BST2() {
        root = null;
    }

    public int nonleaves() { // Method must be declared like this. No
                                // parameters.
        BTNode<T> current = root;
        BTNode<T> previous = null;
        int nonLeafCount = 0;

        MyStack myStack = new MyStack(); // New empty stack

        while (current != null) {
            if (previous == myStack.top()) { // this includes when stack is 
                                                // empty, i.e. current is the
                                                // root.
                myStack.push(current);
                previous = current;
                if (current.left != null) {
                    nonLeafCount++;
                    current = current.left;
                } else if (current.right != null) {
                    nonLeafCount++;
                    current = current.right;
                } else {
                    myStack.pop();
                    current = myStack.top();
                }
            } else if (previous == current.left) {
                previous = current;
                if (current.right != null) {
                    current = current.right;
                } else {
                    myStack.pop();
                    current = myStack.top();
                }
            } else {
                // previous==current.right
                previous = current;
                myStack.pop();
                current = myStack.top();
            }
        }
        return nonLeafCount;
    }

    private static class BTNode<T> {
        BTNode<T> left, right;

        /* ... */
    }
}