像许多新手一样,我的头脑从递归中迸发出来。我在SO上查了很多答案/解释。但我仍然不清楚这个概念。 (这不是作业,我试图重新学习我没学过的东西,递归永远不是一个字符串点)
给定前序遍历,构造二叉树。随着递归,它必须看似简单:)但我无法得到它。
我看 arr的顺序必须是插入节点的顺序。我的错误是:
递归如何插入节点,比如下面的前序?
12, 10, 6, 13
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++)
那是正确的方法吗?或者我接近这一切都是错误的 - 动态编程和递归以及分而治之的混合......
答案 0 :(得分:0)
它不能有左/右孩子。你为root调用它,它没有孩子可以启动。然后你为左边的孩子调用它并在适当的地方创建孩子,并为那些孩子调用函数,依此类推。一旦你向右走,你就不会再次访问左边的孩子而你无法从其子节点上调用的函数到达节点(因为除了递归堆栈之外没有连接树)。
这是给定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)
以上不是代码会发生的原因有两个原因:
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
并停止处理元素。