博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树转列表的实现思路与代码
阅读量:6612 次
发布时间:2019-06-24

本文共 3280 字,大约阅读时间需要 10 分钟。

背景

之前写了一篇的文章,有列表转树的需求自然就会有树转列表的需求,这里我把树转列表的思路与代码再整理一下。

思路分析

需求是什么?

老规矩,上图
图片描述
先说一下整体思路,就是遍历树中的每一个节点,在遍历过程中要把节点的父节点id记录下来,并作为该节点的parentId属性值(保留层级关系,后续根据这个parentId和节点的id可以转回树结构),然后把该节点存入一个列表中。遍历过程完成,也就实现了把树结构转换成了列表结构。

树的遍历方式有两种,一种是深度优先遍历,一种是广度优先遍历,这两种方式思路如下图所示:

  • 广度优先:

图片描述

  • 深度优先

图片描述

思路看这两个图应该理得清楚了

我这里深度优先遍历采用了递归的方式,然后广度优先遍历采用了循环的方式。

执行步骤

先说深度优先吧:

  1. 从第一层开始遍历,遍历该层中所有节点,为每一个遍历到的节点添加上parentId属性,存入结果列表。
  2. 每一个遍历节点存入结果列表后,检测该节点是否存在子节点,如果存在,则将子节点作为数据源重复第一步
  3. 当所有的节点都处理完成后,整个树结构也就完成了转化

再说说广度优先:

  1. 从第一层开始遍历,遍历该层中所有节点,为每一个遍历到的节点添加上parentId属性,存入结果列表。
  2. 每一个遍历节点存入结果列表后,检测该节点是否存在子节点,如果存在,则将子节点数据项push到第一层遍历的列表中(这里相当于在for循环的过程中,修改了被遍历的数组的内容,在循环过程中把它变长了)
  3. 当所有的节点都处理完成后,整个树结构也就完成了转化

代码

深度优先

/** 深度优先遍历树* 一个递归方法* @params tree:要转换的树结构数据* @params list:保存结果的列表结构数据,初始传[]* @params parentId:当前遍历节点的父级节点id,初始为null(因为根节点无parentId)* */function toListDF (tree, list, parentId = null) {    for (let node of tree) {        list.push({            id: node.id,            name: node.name,            children: [],            parentId        })        if (node.children.length !== 0) {            toList(node.children, list, node.id)        }    }}

广度优先:

/** 广度优先遍历树* 一层循环* @params tree:要转换的树结构数据* @output list:返回转换好的列表结构数据* */function toListBF (tree) {    const tempList = tree.slice(0)    const res = []    for (let node of tempList) {        // 向结果中push每一个节点的数据        res.push({            id: node.id,            name: node.name,            children: [],            parentId: node.parentId === undefined ? null : node.parentId        })        // 如果该节点还有子节点,那么将子节点追加到待循环列表的后面        if (node.children.length !== 0) {            // 这里注意,push的是children里面的项            tempList.push(...node.children.map((item) => {                // 这里给每一项加上parentId                item.parentId = node.id                return item            }))        }    }    return res}

这里给一个简单的树结构数据用来测试

const tree = [    {        id: 0,        name: 'root',        children: [            {                id: 1,                name: 'child1',                children: [                    {                        id: 4,                        name: 'child1-1',                        children: []                    },                    {                        id: 5,                        name: 'child1-2',                        children: []                    }                ]            },            {                id: 2,                name: 'child2',                children: [                    {                        id: 6,                        name: 'child2-1',                        children: [                            {                                id: 8,                                name: 'child2-1-1',                                children: []                            }                        ]                    }                ]            },            {                id: 3,                name: 'child3',                children: [                    {                        id: 7,                        name: 'child3-1',                        children: []                    }                ]            }        ]    }]

上面代码直接扔到浏览器中即可运行,可自行看看结果。

总结

树转列表过程中,我这里的深度优先采用了递归方式,可能会对内存占用较多,使用时请自行权衡。

在广度优先的方式中,只用了一层循环,这里有一个核心的点,就是js在循环列表过程中,被循环的列表是可以修改的,比如push一个数据项,这样会让for循环多运行一次,这个点理解之后,我这里的广度优先遍历树的方法就好理解了。

转载地址:http://bgaso.baihongyu.com/

你可能感兴趣的文章
ng-if ng-repeat下的ng-model赋值
查看>>
在HTML5 Canvas中放入图片和保存为图片的方法
查看>>
系统日志出错两例
查看>>
使用域账户ssh登录Cisco交换机
查看>>
linux设置其他用户可以访问本用户下的文件夹的权限
查看>>
思科网络路由知识点整理一
查看>>
最近写了2套软件,WEB版的进销存管理系统,服装连锁店管理软件
查看>>
分享一款flash头像编辑上传利器:社交、博客等网站的好插件
查看>>
穿越生命沼泽
查看>>
改善PHP开发方式
查看>>
遍历窗体上的TextBox并赋String.Empty
查看>>
我的友情链接
查看>>
docker搭建一下Nexus
查看>>
java jdbc
查看>>
java jni调用c/c++ dll
查看>>
mvn命令使用
查看>>
nagios+NRPE+pnp4nagios+ndoutils+mysql监控项目部署(1)
查看>>
HADOOP测试常见问题和测试方法
查看>>
python 简单编写的计算器程序
查看>>
好用的 Mac 应用程序、软件和工具
查看>>