作为练习,我试图将列表转换为二叉树而不使用递归。
这基本上就是我所困的地方。
var items = [
{ a: 1 }, { a: 10 }, { a: 100 }, { a: 20 }, { a: 2 },
{ a: 3 }, { a: 30 }, { a: 300 }, { a: 40 }, { a: 4 }
]
var top = {}
for (var i = 0, n = items.length; i < n; i+=2) {
var a = items[i]
var b = items[i + 1]
top.left = { data: a }
top.right = { data: b }
top = top.right
}
top = top.right
显然是不正确的,它使扩展树只被创建了一个分支,因此它基本上只是一个链表,在每个级别上只有一小片叶子。
/\
/\
/\
/\
/\
\
我很难理解如何向下遍历树的所有分支,并将节点按顺序排列在二叉树中,从而可以在/上进行迭代以原始顺序遍历,它们在列表中。我不确定这叫什么,如果我应该按顺序/预定/后置来执行某些版本的DFS / BFS,我不太确定。想知道是否可以在JS中演示如何做到这一点。
我不确定输出应该是什么,但是如果我不得不猜测它将是这样的:
top
1 10
100 20 2 3
30 300 40 4
答案 0 :(得分:2)
您可以使用两个索引,一个用于 node 列表,另一个用于 target 列表。然后,将接下来的两个节点放在 target 节点的左侧和右侧。
继续直到没有更多节点可用为止。
此树没有空的起始节点。
var items = [{ a: 1 }, { a: 10 }, { a: 100 }, { a: 20 }, { a: 2 }, { a: 3 }, { a: 30 }, { a: 300 }, { a: 40 }, { a: 4 }],
tree = items[0],
i = 1,
j = 0;
while (i < items.length) {
items[j].left = items[i++];
if (i >= items.length) break;
items[j].right = items[i++];
j++;
}
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
一种小小的方法。
var items = [{ a: 1 }, { a: 10 }, { a: 100 }, { a: 20 }, { a: 2 }, { a: 3 }, { a: 30 }, { a: 300 }, { a: 40 }, { a: 4 }],
tree = items[0],
i = 1,
side = 'right';
while (i < items.length) {
side = { left: 'right', right: 'left' }[side];
items[(i - 1) >> 1][side] = items[i++];
}
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:1)
确定代码如下。这将生成给定items
中提到的OP所描述的二叉树。该函数将使用while
和for
循环
整个想法是跟踪我们要在数组中插入新值的对象。
让我们考虑我们有这样的项目数组
var items = [
{ a: 1 }, { a: 10 }, { a: 100 }, { a: 20 }, { a: 2 },
{ a: 3 }, { a: 30 }, { a: 300 }, { a: 40 }, { a: 4 }
]
首先,我们创建一个空对象。 obj = {}
。此时,我们需要在.left
中添加.right
和obj
。因此,我们最初设置了next = [obj]
。
在for
中,.left
和right
将被添加到obj
中,因为next
仅包含一个元素。因此,对象像这样循环。
{
left:{ a: 1 },
right:{ a: 10 }
}
现在,在下一站中,我们想left
和right
到当前对象的两个键。因此,我们将两者都推送到next
数组中。
这样下一个数组看起来
[{},{ a: 1 },{ a: 10 }]
请注意,i = 1
现在在下一个for
循环中,left
和right
被添加到array的最后两个元素。因为array中的元素正在引用的属性。宾语。因此,这将使obj变异。 obj
{
left:{ a: 1,left:{ a: 100 },right:{ a: 20 }},
right:{ a: 10, right:{ a: 2 },left:{ a: 3 }}
}
现在next
将是
[{},{ a: 1 },{ a: 10 },{ a: 100 },{ a: 20 },{ a: 2 },{ a: 3 }]
现在,在下一个循环中,下一个剩余的4
元素将被添加到left
和right
的{{1}}和{ a: 100 }
的子级中。并且{ a: 20 }
将成为items.length
,它将0
return
。
obj
答案 2 :(得分:1)
我们需要决定的第一件事是树的结构。与其拥有一个单独的根节点,不如将列表的第一个元素作为根。因此,我们的树数据结构可以定义如下:
// A Tree(a) is one of:
// - null
// - tree(a, Tree(a), Tree(a))
const tree = (value, left, right) => ({ value, left, right });
因此,我们的输出树将如下所示:
1
|
+------------+------------+
| |
10 100
| |
+---------+---------+ +-----+-----+
| | | |
20 2 3 30
| | | |
+-----+-----+ +-+-+ +--+--+ +--+--+
| | | | | | | |
300 40 4 null null null null null
| | |
+--+--+ +--+--+ +--+--+
| | | | | |
null null null null null null
如果我们要使用递归,那么代码很简单,因为树是递归的数据结构:
const buildTree = (xs, i = 0) => i >= xs.length ? null :
tree(xs[i], buildTree(xs, 2 * i + 1), buildTree(xs, 2 * i + 2));
将它们放在一起:
// A Tree(a) is one of:
// - null
// - tree(a, Tree(a), Tree(a))
const tree = (value, left, right) => ({ value, left, right });
const buildTree = (xs, i = 0) => i >= xs.length ? null :
tree(xs[i], buildTree(xs, 2 * i + 1), buildTree(xs, 2 * i + 2));
console.log(buildTree([1, 10, 100, 20, 2, 3, 30, 300, 40, 4]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
我将保留它作为练习,将递归程序转换为迭代程序。
这是将任何递归函数转换为迭代函数的算法方法。首先,将函数转换为连续传递样式:
const buildTree = (xs, i = 0, k = x => x) => i >= xs.length ? k(null) :
buildTree(xs, 2 * i + 1, left =>
buildTree(xs, 2 * i + 2, right =>
k(tree(xs[i], left, right))));
接下来,将连续替换为包含连续的所有必需的自由变量的数据结构。另外,用包含功能的逻辑applyCont
的应用程序替换延续调用:
const buildTree = (xs, i, k = null) => i >= xs.length ? applyCont(k, null) :
buildTree(xs, 2 * i + 1, { xs, i, k });
const applyCont = (k, x) => k === null ? x :
!k.hasOwnProperty("x") ? buildTree(k.xs, 2 * k.i + 2, { x, xs: k.xs, i: k.i, k: k.k }) :
applyCont(k.k, tree(k.xs[k.i], k.x, x));
如果您注意到,延续的结构现在类似于链接列表。实际上,您可以将延续视为框架的堆栈(即程序堆栈)。现在,可以很容易地将此递归代码转换为迭代代码,如下所示:
const buildTree = xs => {
var i = 0, stack = null;
loop: do {
while (i < xs.length) {
i = 2 * i + 1;
k = { i, k };
}
var x = null;
while (k) {
if (!k.hasOwnProperty("x")) {
i = 2 * k.i + 2;
k.x = x;
continue loop;
}
k = k.k;
x = tree(k.xs[k.i], k.x, x);
}
return x;
} while (true);
};
希望有帮助。
答案 3 :(得分:0)
@AaditMS这里是根据您发送的内容进行的粗略迭代。谢谢。
var items = [ 1, 10, 100, 20, 2, 3, 30, 300, 40, 4 ]
var tree = {}
var node = tree
var stack = [ node ]
var i = 0
while (stack.length) {
var node = stack.shift()
node.value = items[i]
if (node.value) {
node.left = {}
stack.push(node.left)
node.right = {}
stack.push(node.right)
}
i++
}
console.log(JSON.stringify(tree, null, 2))