这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
对于常见的树形数据进行拍扁操作是前端经常会遇到的工作内容之一
对于树形数据拍扁,我们有多种方法可以实现。
递归实现
使用递归算法,从根节点开始,不断地遍历每个子节点,将数据拍扁成一维数组的形式。
function treeToArray(tree, result = []) {
for (const node of tree) {
result.push(node);
if (node.children && node.children.length) {
treeToArray(node.children, result);
delete node.children;
}
}
return result;
}
这个函数接受一个树结构(一个节点数组,每个节点都有一个children
数组),并递归地将其展平为一维数组。
它通过迭代树的每个节点并将其添加到result
数组中来工作。 如果节点有子节点,它会使用子节点和result
数组递归调用treeToArray
,然后从原始节点中删除children
属性(因为其不再需要)。
该函数返回result
数组,其中包含原始树的所有节点,按深度优先顺序排列。
栈实现
另一种方法是使用栈。 将根节点放入栈中,然后弹出栈顶元素,将其子节点压入栈中,然后重复此操作,直到栈为空。
function treeToArray(tree) {
const stack = [...tree];
const result = [];
while (stack.length) {
const node = stack.pop();
result.push(node);
if (node.children && node.children.length) {
stack.push(...node.children);
delete node.children;
}
}
return result;
}
该函数接受一个树结构,并使用栈将其展平为一维数组。它通过遍历树的每个节点,将其添加到result
数组中,并从原始节点中删除children
属性来工作。它返回result
数组,其中包含原始树的所有节点,按深度优先顺序排列。
队列操作
另一种方法是使用队列。我们可以从根节点开始,将其子节点添加到队列中,并将根节点添加到结果数组中,然后从队列的末尾取出元素,将其子节点添加到队列中,并将其添加到结果数组中;一直重复此操作,直到队列为空。
function treeToArray(tree) {
const queue = [...tree];
const result = [];
while (queue.length) {
const node = queue.shift();
result.push(node);
if (node.children && node.children.length) {
queue.push(...node.children);
delete node.children;
}
}
return result;
}
这个函数的工作原理首先将根节点推入队列。然后,在循环中,它从队列中出列第一个节点,将其添加到结果数组中,并检查它是否有任何子节点。如果有,它将它们入列到队列中,并从当前节点中删除children
属性。
此过程将持续到队列为空,此时函数将返回展平的result
数组。
堆栈和队列两种方法的时间和空间复杂度都是O(n),其中n是树中的总节点数。但是,基于队列的方法更直观,更容易阅读,因为它遵循更自然的宽度优先遍历顺序。