从预订中建立BST

时间:2013-03-01 00:04:52

标签: algorithm tree binary-search-tree traversal

像许多新手一样,我的头脑从递归中迸发出来。我在SO上查了很多答案/解释。但我仍然不清楚这个概念。 (这不是作业,我试图重新学习我没学过的东西,递归永远不是一个字符串点)

给定前序遍历,构造二叉树。随着递归,它必须看似简单:)但我无法得到它。

arr的顺序必须是插入节点的顺序。我的错误是:

  1. 如果节点已经有左/右怎么办?这是如何工作的?
  2. 递归如何插入节点,比如下面的前序?

    12, 10, 6, 13
    
  3. 15是root,5,3和left

    如果10岁的孩子正确插入6个?

        12
     10   13
    6*
    

    这是骨架代码:

    main()
    {
       int[] arr = {};
       //make the first node a root node.
       node n = new node(arr[0]);
       buildbst(n, arr, 0)
    }
    
    buildbst(node root, int[] arr, int i)
    {
       if (i == arr.length) return;
    
       if (arr[i] < root.data)
          root.left = new node (arr[i]);
       else
          root.right = new node(arr[i]);
    
       buildbst(root.left, arr, i++);
       buildbst(root.right, arr, i++);
    }
    

    编辑:

    我刚才意识到,如果我传入递归调用buildbst(root.left, arr+i, i++) 那是正确的方法吗?或者我接近这一切都是错误的 - 动态编程和递归以及分而治之的混合......

1 个答案:

答案 0 :(得分:0)

  1. 它不能有左/右孩子。你为root调用它,它没有孩子可以启动。然后你为左边的孩子调用它并在适当的地方创建孩子,并为那些孩子调用函数,依此类推。一旦你向右走,你就不会再次访问左边的孩子而你无法从其子节点上调用的函数到达节点(因为除了递归堆栈之外没有连接树)。

  2. 这是给定12, 10, 6, 13时应该发生的事情:

    • 创建根12
    • 致电buildbst(node(12), arr, 1)
      • 创建node(12).left = node(10)
      • 致电buildbst(node(10), arr, 2)
        • 创建node(10).left = node(6)
        • 致电buildbst(node(6), arr, 3)
          • 13 > 12,必须是12的正确孩子,所以不要做任何事情
        • 13 > 12,必须是12的正确孩子,所以不要做任何事情
      • 创建node(12).right = node(13)
      • 致电buildbst(node(13), arr, 3)
        • 哦,看,没有更多元素,我们已经完成了。
  3. 以上不是代码会发生的原因有两个原因:

    • 您的代码只会创建一个左子或右子,而不是两者(因为if-else
    • 您的代码没有must be right child of '12'检查,这有点复杂

    以下代码应涵盖它。

    node buildbst(int[] arr)
    {
       node n = new node(arr[0]);
       // 9999999999 is meant to be > than the biggest element in your data
       buildbst(n, arr, 1, 9999999999);
       return node;
    }
    
    int buildbst(node current, int[] arr, int i, int biggestSoFar)
    {
        if (i == arr.length) return i;
    
        // recurse left
        if (arr[i] < current.data)
        {
          current.left = new node(arr[i++]);
          i = buildbst(current.left, arr, i, current.data);
        }
    
        // recurse right
        if (i < arr.length && arr[i] < biggestSoFar)
        {
          current.right = new node(arr[i++]);
          i = buildbst(current.right, arr, i, biggestSoFar);
        }
    
        return i;
    }
    

    <强>解释

    biggestSoFar的目的是阻止:

        15                          15
       /                            /\
      5     versus (the correct)   5  20
     / \                          /
    1   20                       1
    

    例如,当从15向左递归时,我们需要在获得元素> 15后立即停止处理元素,这将在我们获得20时发生。因此,如果我们得到更大的值,我们会传递current.data并停止处理元素。

    例如,当我从5递归时,我们需要在获得元素> 15时立即停止处理元素,这将在我们获得20时发生。因此,如果我们得到更大的值,我们会传递biggestSoFar并停止处理元素。