前言
我的朋友小菜同学是一个学习时长两年半的前端boy。面试的时候,面试官让他写一个扁平数据结构转Tree.他思考片刻不好意思的说“你干嘛啊,哎呦”。可想而知之,这次的面试以失败告终了。
“斯人已去,生者如斯”,让我们看看这个东西到底怎么写!
Main
扁平数据结构:扁平数据结构是指所有数据都在同一层级上的数据结构。如下所示。
const flatData = [
{id: 1, name: 'Node 1', parentId: null},
{id: 2, name: 'Node 1.1', parentId: 1},
{id: 3, name: 'Node 1.1.1', parentId: 2},
{id: 4, name: 'Node 1.1.2', parentId: 2},
{id: 5, name: 'Node 1.2', parentId: 1},
{id: 6, name: 'Node 2', parentId: null},
{id: 7, name: 'Node 2.1', parentId: 6},
{id: 8, name: 'Node 2.2', parentId: 6},
{id: 9, name: 'Node 2.2.1', parentId: 8},
{id: 10, name: 'Node 2.2.2', parentId: 8}
];
树形结构: 树形数据结构则是一种多级嵌套的数据结构。如下所示。
[
{
id: 1,
name: 'Node 1',
parentId: null,
children: [
{
id: 2,
name: 'Node 1.1',
parentId: 1,
children: [
{id: 3, name: 'Node 1.1.1', parentId: 2},
{id: 4, name: 'Node 1.1.2', parentId: 2}
]
},
{id: 5, name: 'Node 1.2', parentId: 1}
]
},
代码实现
1.递归算法实现
function buildTree(flatData, parentId = null) {
const tree = [];
flatData.forEach((node) => {
if (node.parentId === parentId) {
const children = buildTree(flatData, node.id);
if (children.length > 0) {
node.children = children;
}
tree.push(node);
}
});
return tree;
}
const treeData = buildTree(flatData, null);
console.log(treeData);
代码中的 buildTree
函数接收两个参数:flatData
表示扁平数据结构,parentId
表示要构建树的父节点。在函数中,我们首先创建一个空数组 tree
用于保存生成的树节点。
接下来,我们遍历扁平数据结构中的每个节点,如果节点的 parentId
与指定的父节点匹配,则将该节点加入到树中。
在将节点加入树中之前,我们通过递归调用 buildTree
函数来生成该节点的子节点。如果子节点存在,则将其添加到节点的 children
属性中。
最后,我们返回树形结构。
2.迭代
采用迭代的方式来构建树形结构,可以使用一个哈希表来存储每个节点的引用。遍历扁平数据结构时,如果该节点的父节点已经在哈希表中,则将该节点添加到父节点的 children
属性中,否则将该节点添加到哈希表中。
function buildTree(flatData) {
const tree = [];
const nodes = {};
flatData.forEach((node) => {
nodes[node.id] = {...node, children: []};
});
Object.values(nodes).forEach((node) => {
const parentId = node.parentId;
if (parentId === null) {
tree.push(node);
} else {
nodes[parentId].children.push(node);
}
});
return tree;
}
在代码中,我们首先使用 forEach 方法遍历扁平数据结构,并将每个节点添加到哈希表中。哈希表中的键为节点的 id
,值为一个新的对象,其中包含该节点的所有属性以及一个空数组 children
用于存储其子节点。
接下来,我们再次使用 forEach 方法遍历哈希表中的每个节点,如果该节点的 parentId
为 null,则将该节点添加到根节点中,否则将该节点添加到其父节点的 children
属性中。
由于哈希表可以实现常数时间的查找操作,因此该算法的时间复杂度为 O(n)。
结束语
本章的内容就到此结束了,希望对大家有所帮助。点个赞吧 :+1:
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!