[英]Tail Recursive Binary Tree Search Function JS
我正在尝试编写一个尾递归 function contains(tree,element) 如果该元素存在于二叉树中则返回 true,否则返回 false。
我写了递归 function,问题是我不知道如何让它尾递归
let leaf = { val: 6 }
let tree = {
val: 10,
sx: {
val: 5,
sx: {
val: 13
},
dx: leaf
},
dx: {
val: 32,
sx: null,
dx: null
}
}
function contains(t,x) {
if(t.val == x)
return 1;
let res = 0 ;
if(t.sx)
res += contains(t.sx,x)
if(t.dx)
res += contains(t.dx,x)
return Boolean(res)
}
console.log(contains(tree,6))
我认为这不可能使完全尾递归,因为递归调用的次数可能是 1 或 2(或 0)- 在 2 的情况下,您不能无条件返回 function 的最终计算,因为您不知道特定的递归调用是否将是 function 的最终计算。
也就是说,您可以改进您的代码。 如果val
匹配,则返回true
,而不是添加到res
变量,如果它们为真,则立即返回第一个递归调用。 第二次调用可以进行尾递归,因为在那个时候,没有什么可以检查分支了。
let leaf = { val: 6 } let tree = { val: 10, sx: { val: 5, sx: { val: 13 }, dx: leaf }, dx: { val: 32, sx: null, dx: null } } function contains(t, x) { if (t.val == x) { return true; } // Recursive, but not tail recursive: if (t.sx && contains(t.sx, x)) { return true; } // Tail recursive: return.t?dx: false. contains(t,dx; x). } console,log(contains(tree, 6))
对于那些感兴趣的人,我留下二叉搜索树的尾递归版本
let leaf = { val: 7}
let tree = {
val: 10,
sx: {
val: 5,
sx: {
val: 4
},
dx: leaf
},
dx: {
val: 32,
sx: null,
dx: null
}
}
function _contains(t,x) {
if(t.val == x)
return 1;
if(x < t.val && t.sx)
return _contains(t.sx,x)
else if(t.dx)
return _contains(t.dx,x)
}
function contains(t,x){
return Boolean(_contains(t,x));
}
虽然这里的讨论已经提出了二叉搜索树的尾递归解决方案,但似乎可以为任意二叉树(或者实际上是任何树)做一个尾递归版本。技巧是我们的核心 function 将在一组节点上运行,而不是在单个节点上运行。
在这里,我们对树进行广度优先遍历,在找到值或用完节点时停止。 我们的递归调用在输入数组的尾部加上节点的左右子节点上运行。 (不存在或null
个节点将被忽略。)
公共 function 只是将输入树包装在一个数组中,并将其传递给我们的主 function。
const _contains = ([t, ...ts], x) => t == undefined? false: t.val == x? true: _contains (ts.concat (t.sx || []).concat (t.dx || []), x) const contains = (t, x) => _contains ([t], x) let tree = {val: 10, sx: {val: 5, sx: {val: 13}, dx: {val: 6}}, dx: {val: 32, sx: null, dx: null}}; [10, 12, 13, 32, 42].forEach (x => console.log (`${x} --> ${contains (tree, x)}`))
根据一般原则,我不愿意这样做,但是如果我们将孩子推到数组上并在索引上重复出现,这肯定会变得更加有效,就像这样:
const push = (x) => (xs) =>
x ? ((xs .push (x)), xs) : xs
const _contains = (ts, i, x) =>
i >= ts .length
? false
: ts [i] .val == x
? true
: _contains (push (ts [i] .dx) (push (ts [i] .sx) (ts)), i + 1, x)
const contains = (t, x) =>
_contains ([t], 0, x)
但要点很简单,通过使用节点数组,我们可以为似乎永远不会出现的 TCO 做好准备,除非您是Safari用户。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.