[英]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.