【问题标题】:Saving the in-order visit of a binary tree in an array将二叉树的有序访问保存在数组中
【发布时间】:2020-02-03 15:51:53
【问题描述】:

问题如下: 有没有一种算法,给定一棵二叉树T 和一个数组,允许在数组中存储对应的按顺序访问树的结果?

“正常”有序访问的伪代码:

inOrder(x){ // x is a node of a binary tree
   if(x != NIL){ // the node is not null
      inOrder(x.left)
      print(x.key)
      inOrder(x.right)
   }
}

// Function calling inOrder
printInOrder(T){ // T is a binary tree
   inOrder(T.root) // T.root is the root of the tree
}

示例: 给定以下树

     5 
   /   \
  3     8
 / \   / 
2   7 1   

上面的算法应该输出2 3 7 5 1 8

我确信这是可以实现的,应该不会太难,但我目前正在为这个问题而苦苦挣扎。

【问题讨论】:

  • 提示:跟踪数组中下一个元素应该写入的当前索引。如果您必须在没有数组以外的任何可变状态的情况下执行此操作,则将该索引作为参数并返回新的当前索引应该是什么。
  • 我已经知道第一个解决方案,虽然我觉得它可以改进(我真的很不喜欢它)。关于第二个:如何确定下一个元素应该保存在哪里?在示例中,我使用了几乎完整的二叉树,但该算法应该适用于每棵树。
  • 将变量(包括要填充输出的数组)作为参数传递给inOrder函数是否有任何限制?
  • 您只需要将节点保存在数组中,而不是使用“print(x.key)”语句。取一个全局数组 "inorderNodes" 和一个全局 int 变量 "idx" 并从驱动方法中设置 "idx=0",写入 "inorderNodes[idx] = x.key; idx++;"就是这样。
  • inOrder参数没有限制

标签: algorithm binary-tree binary-search-tree inorder


【解决方案1】:

写入数组(而不是打印)意味着您需要跟踪要写入数组中的哪个索引。如果您需要在数组本身之外没有任何可变状态的情况下执行此操作,则需要将当前索引作为参数传递,并返回新的当前索引。

下面的代码是用static single assignment form 编写的,所以即使是局部变量也不会发生变异。如果不需要,则可以稍微简化代码。我假设数组长度是已知的;如果需要计算,那是一个单独的问题。

inOrder(x, arr, i) {
    if(x == NIL) {
        return i
    } else {
        i2 = inOrder(x.left, arr, i)
        arr[i2] = x.key
        i3 = inOrder(x.right, arr, i2 + 1)
        return i3
    }
}

getArrayInOrder(T, n) {
    arr = new array of length n
    inOrder(T.root, arr, 0)
    return arr
}

【讨论】:

    【解决方案2】:

    首先关于数组:为了填充数组,您需要事先知道数组的长度。如果您不需要指定实例化数组的长度(取决于您使用的语言),那么这并不是真正的数组。它是一种动态数据结构,其大小由语言实现自动增加。

    现在我假设您事先不知道树的大小。如果您确实知道大小,则可以实例化一个指定大小的数组。假设你不知道数组的大小,你需要使用像 Java 中的 ArrayList 这样的动态数据结构。

    因此,在代码中的每个 print(x.key) 处,只需将 x.key 附加到列表中(如 list.add(x.key) )。遍历完成后,您可以将List 转为array

    您也可以使用iterative 版本的遍历。

    递归方法的一个简单解决方案是使用单个元素数组来跟踪索引,例如:

    void inOrder(x, int[] idx, int[] arr):
        if x != NIL:
           inOrder(x.left, idx, arr)
           arr[idx[0]++] = x.key
           inOrder(x.right, idx, arr)
    

    虽然我确信可能有其他方法会变得很麻烦(也许)。反正我更喜欢迭代版本。

    【讨论】:

      【解决方案3】:

      如果您的语言/用例允许将整数放入数组中,您可以将索引存储在数组中。我要倒退,因为这样更简单:

      inOrder(x, arr){
         if(x != NIL){
            inOrder(x.right)
            arr[--arr[0]] = x.key
            inOrder(x.left)
         }
      }
      
      saveInOrder(T, n){
         arr = new int[n]
         arr[0] = n
         inOrder(T.root, arr)
         return arr
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-18
        • 2021-02-15
        相关资源
        最近更新 更多