用Java将二叉树展平为数组

用Java将二叉树展平为数组,java,arrays,algorithm,binary-tree,functional-programming,Java,Arrays,Algorithm,Binary Tree,Functional Programming,我在Java中找到了将二叉树展平为数组的方法。我很难理解它是如何工作的 代码如下: private static int FlattenTreeIntoArray(Node tree, int[] array, int i) { if (tree == null) return i; // Flatten left subtree i = FlattenTreeIntoArray(tree.Left, array, i); // Get data from the

我在Java中找到了将二叉树展平为数组的方法。我很难理解它是如何工作的

代码如下:

private static int FlattenTreeIntoArray(Node tree, int[] array, int i)
{
    if (tree == null) return i;
    // Flatten left subtree
    i = FlattenTreeIntoArray(tree.Left, array, i);
    // Get data from the current node
    array[i] = tree.Data;
    // Flatten right subtree
    i = FlattenTreeIntoArray(tree.Right, array, i + 1);
    return i;
} 
我的问题如下:

  • 这是helper方法,实际的方法是如何调用的,或者什么是作为参数传递的(
    int[]array
    int i
    )?我们不知道二叉树的大小

  • 这个方法是如何工作的?当
    null
    时,它返回
    i
    。这是什么意思

  • 扁平化是如何发生的?为什么将
    i+1
    传递到
    右树
    ,而将
    i
    传递到
    左树

  • 如果您可以使用此二叉树进行演示,则很容易理解:

    这是helper方法,实际的方法是如何调用的,或者 什么作为参数传递给int i和int[]数组——我们不知道 知道二叉树的大小

    int i
    是数组中的索引-您希望从0开始,因为它是第一个元素。如果您不知道树的大小,最好使用
    LinkedList

    How does the method function: when the tree is null, it returns i. what does that mean?
    
    这意味着您正在检查一个不存在的“子项”,因此您返回的索引不变

    扁平化是如何发生的?为什么i+1被传递到右树,而我 到左边的树

    您将i传递到左树,因为该调用将通过递归证明传回树中当前节点上的数据所属的索引。然后必须告诉右树索引已增加,因为根据定义,右树中的任何内容的值都将高于当前节点

    您的调用将是
    platteTreeInToArray(my_tree,my_array,0)
    where
    my_array.length==9

    在第一次调用时,左子树是根节点
    3
    ,它通过索引0。调用左子树后,new左子树是一个包含数据1的叶子。当以1作为根调用
    FlattTreeInToArray
    时,它将向
    FlattTreeInToArray
    传递一个空子级,从而返回0

    您的下一个调用将是
    my_array[0]=1
    ,因此数组的第一个元素是树中的最低数字。然后它将递增并返回索引


    因此,最终根为3的调用将返回
    1
    作为索引,并将调用
    my_array[1]=3
    。诸如此类,冲洗并重复。

    这是一个简单的递归示例,一旦理解了这一点,所有递归树算法都应该开始有意义了。我将尽力回答您的问题:

    这是helper方法,实际的方法是如何调用的,或者什么作为参数传递给int i和int[]数组--我们不知道二叉树的大小

    查看代码,由于这是一个面试类型的问题,我们将假设int[]数组足够大,可以容纳所有内容

    i
    似乎是要填充的数组的当前索引,因此展开树的第一个调用将
    i
    设置为0

    此方法还返回一个整数,该整数是到目前为止已填充的元素数。这意味着最终返回将返回树的全长(以及数组中填充的元素数)

    该方法如何工作:当树为null时,它返回i。这是什么意思?

    这假设如果没有子节点,
    节点的左或右字段指向null。由于我们使用
    i
    来维护我们在数组中的位置,因此如果没有子级,我们不会更新
    i
    的值

    扁平化是如何发生的?为什么i+1传递到右树而i传递到左树。 通过找到最左边的节点并将其放入
    i
    ,可以实现展平。然后找到下一个最左边的节点并将其放入
    i+1

    让我们浏览一下您给出的树示例:

    节点=8 i=0; 数组={}

    获取根的左节点(3)并递归调用此展平方法,该方法获取3的左节点(1),当获取1的左节点(null)时,再次递归调用展平方法。返回
    i
    =0。 现在我们使用的是节点1的展平方法
    array[0]=节点1的值
    =`array[0]=1

    现在调用节点1的右字段并展平递增的i。节点1的右字段为null,因此我们返回i的当前值(即1)

    现在我们回到节点1的展平方法中,找到了左、右递归,并到达了方法的末尾,因此我们返回当前值
    i
    ,即1

    现在我们回到节点3的展平方法。我们刚刚完成了对左字段的展平方法的调用,该方法返回的值为1,现在我们将i设置为

    现在我们用节点3的值更新数组

    array[1] = 3;
    
    现在我们用递增的i so
    i=2展平节点3的右字段(节点6)


    希望对你有所帮助除了其他答案,我还制作了这个gif来演示算法的执行。您可以在左侧看到必须处理的元素,在右侧看到数组


    这是一个非常实用的代码(请参阅)。这种类型的树遍历称为

    让我们做一些观察
  • 这棵树只是被阅读,从未被改写过
  • 在每个调用中,
    i
    仅递增一次,前提是当前节点不为null<代码>i
  • 从不递减
  • 数组
    仅写入。唯一的写入是在索引
    i
    上。不使用
    数组执行任何其他操作(传递其引用除外)
  • 当前节点数据在处理左子树和右子树之间写入数组
    array[1] = 3;
    
    // tree and MAX_TREE_SIZE come from outside
    int[] array = new int[MAX_TREE_SIZE];
    int tree_size = FlattenTreeIntoArray(tree, array, 0);