【问题标题】:Creating Java binary search tree创建Java二叉搜索树
【发布时间】:2012-03-26 06:32:20
【问题描述】:

这里是 Node 类:

public class Node
{
    private int _info;
    private Node _left;
    private Node _right;

    public Node()
    {
        //this._info = Integer.MIN_VALUE;
        this._left = null;
        this._right = null;
    }


    public int getInfo()
    {
        return _info;
    }

    public void setInfo(int _info)
    {
        this._info = _info;
    }

    public Node getLeft()
    {
        return _left;
    }

    public void setLeft(Node _left)
    {
        this._left = _left;
    }

    public Node getRight()
    {
        return _right;
    }

    public void setRight(Node _right)
    {
        this._right = _right;
    }  
}

我如何创建树:

public class BalancedBinaryTree
{
    private ArrayList<Integer> _numbers;
    private Node _root;

    public BalancedBinaryTree(ArrayList<Integer> numbers)
    {
        this._numbers = new ArrayList<>();
        this._numbers.addAll(numbers);
        Collections.sort(this._numbers);

        this._root = new Node();

        this.create(this._root, 0, this._numbers.size());
    }

    private void create(Node tree, int i, int j)
    {
        if (i < j)
        {
            int m = i + (j - i) / 2;

            tree.setInfo(this._numbers.get(m));

            tree.setLeft(new Node());
            create(tree.getLeft(), i, m);

            tree.setRight(new Node());
            create(tree.getRight(), m + 1, j);
        }
    }

这个方法计算深度:

    public static int getDepth(Node node)
    {
        if (node == null)
        {
            return 0;
        }
        else
        {
            int max = 0;
            if (getDepth(node.getLeft()) > getDepth(node.getRight()))
            {
                max = getDepth(node.getLeft());
            }
            else
            {
                max = getDepth(node.getRight());
            }
            return max + 1;
        }
    }

这两个结合起来应该按层次打印树:

    public static void printLevel(Node node, int levelToDisplay, int currentLevel)
    {
        if (node != null)
        {
            printLevel(node.getLeft(), levelToDisplay, currentLevel);
            if (currentLevel == levelToDisplay)
            {
                System.out.print(node.getInfo() + " ");
            }
            currentLevel++;
            printLevel(node.getRight(), levelToDisplay, currentLevel);
        }
    }

    public static void printLevels(Node node)
    {
        for (int i = 0; i < getDepth(node); i++)
        {
            System.out.println("Level :" + i);
            printLevel(node, i, 0);
            System.out.println();
        }
    }

在我的测试课中:

    testNumbers.add(15);
    testNumbers.add(20);
    testNumbers.add(25);
    testNumbers.add(30);
    testNumbers.add(35);
    testNumbers.add(40);
    testNumbers.add(45);


    BalancedBinaryTree tree = new BalancedBinaryTree(testNumbers);
    BalancedBinaryTree.printLevels(tree.getRoot());

我得到这个输出:

Level :0
0 15 20 30 
Level :1
0 0 25 0 35 40 
Level :2
0 0 0 45 
Level :3
0

我应该得到

Level :0
30
Level :1
20 40
Level :2
15 25 35 45
  1. getDepth 方法有什么问题,因为它似乎返回 4 个级别而不是 3 个?
  2. 为什么会有额外的节点? (那些零)

我很确定我解决了这些问题,但我需要解释以下内容:

这是修改后的printlevel方法:

public static void printLevel(Node node, int levelToDisplay, int currentLevel)
{
    if (node.getLeft() != null && node.getRight() != null)           
    {
        printLevel(node.getLeft(), levelToDisplay, currentLevel+1);  
        if (currentLevel == levelToDisplay)
        {
            System.out.print(node.getInfo() + " ");
        }
        printLevel(node.getRight(), levelToDisplay, currentLevel+1);  
    }
}

如您所见,我现在测试当前节点是否有子节点,而不是检查当前节点是否存在,这就是为什么出现这些零的原因,因为遍历到达了没有为其左右子节点分配信息的叶子。

我想了解的是递增currentLevel 然后将其传递给printLevel 的调用和简单地将currentLevel+1 传递给调用之间的区别。不应该是一样的吗?

还有getDepth 函数:

public static int getDepth(Node node)
{
    if (node.getLeft() == null && node.getRight() == null)
    {
        return 0;
    }
    else
    {
        int max = 0;
        if (getDepth(node.getLeft()) > getDepth(node.getRight()))
        {
            max = getDepth(node.getLeft());
        }
        else
        {
            max = getDepth(node.getRight());
        }
        return 1 + max;
    }
}

同样的事情:遍历到达叶子并对其子节点再次调用,因此返回一个额外的级别,因此解决方案是测试当前节点是否有子节点,而不是检查当前节点是否退出。

【问题讨论】:

  • 欢迎来到 Stack Overflow!让陌生人通过检查发现代码中的错误是没有效率的。您应该通过使用调试器或打印语句来识别(或至少隔离)问题,并在简单的数据集上运行,然后返回更具体的问题(一旦您将其缩小到 10 行 @987654321 @)。
  • 这是作业吗?如果是这样,请将其标记为这样。
  • @OliCharlesworth 就像我是唯一一个发过这样帖子的人。所以,更具体地说,在 create 我有 2 个构造函数调用 Node 但是如果我在构造函数中放置一个打印,打印的数量不对应所以构造函数在该递归函数中的某个点被调用太多次
  • @oneNewbieCoder:你说得对,这几乎不是不适合 Stack Overflow 问题的唯一实例。我并不是说这听起来很刺耳,但您需要帮助我们帮助您。你比这里的任何人都更能调试你的代码;所以你应该这样做以确定它的行为与你的预期不同的地方。一旦你有了它,你就可以开始删除你的代码,直到问题消失。一旦你有了仍然显示问题的最小测试用例(应该是大约 10 行),那么就是时候在这里发布问题了。

标签: java binary-tree


【解决方案1】:

getDepth 方法有什么问题,因为它似乎返回 4 个级别而不是 3 个?

从您的打印方法看来,您将级别从 0 编号到 n(树的根为 0)。但是,您的 getDepth 方法永远不会返回 0。 两件事:if (node != null) 这个检查似乎没有多大意义。 Null 似乎不是允许的输入(因为根是在构造树时构造的)。如果是这种情况(并且您确实想检查它),则异常可能更合适。 主要问题似乎是这样的:return max + 1; 所以返回的最小值是0+1,也就是1。

作为一个小旁注:我会保存 getDepth 的两个递归调用的值,这将大大提高性能。 此外,如果您确实使用短变量名称,例如 i、m 或 j(以非循环索引的方式),记录它们的含义会很有帮助。

关于您的第一个问题: tree.setLeft(new Node()); 到目前为止,这个节点的价值是多少?如果递归调用中的i &lt; j codition 不通过会发生什么?如果你能回答这些问题,你应该能够自己修复代码。

【讨论】:

  • @oneNewbieCoder currentLevel++ 和传递 currentLevel+1 不仅应该做同样的事情,他们实际上也在做同样的事情(在你的情况下)。是的,您修改后的方法有效,您正确识别了问题。您的解决方案的唯一问题(在我看来)是包含 0 的节点仍然存在。这可能会导致您可能希望稍后实现的方法(如添加、删除等)出现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
相关资源
最近更新 更多