一维数组构建树结构,同时标记叶子结点(非递归,JavaScript版)

给定包含节点关系的一维数组数据,如下:
[
    {
        "name": "四川省",
        "id": 1,
        "parentId": null
    },
    {
        "name": "成都市",
        "id": 2,
        "parentId": 1
    },
    {
        "name": "绵阳市",
        "id": 3,
        "parentId": 1
    },
    {
        "name": "自贡市",
        "id": 4,
        "parentId": 1
    },
    {
        "name": "泸州市",
        "id": 5,
        "parentId": 1
    },
    {
        "name": "达州市",
        "id": 6,
        "parentId": 1
    },
    {
        "name": "锦江区",
        "id": 7,
        "parentId": 2
    },
    {
        "name": "青羊区",
        "id": 8,
        "parentId": 2
    },
    {
        "name": "金牛区",
        "id": 9,
        "parentId": 2
    },
    {
        "name": "武侯区",
        "id": 10,
        "parentId": 2
    },
    {
        "name": "成华区",
        "id": 11,
        "parentId": 2
    },
    {
        "name": "香木林路",
        "id": 12,
        "parentId": 11
    },
    {
        "name": "建工路",
        "id": 13,
        "parentId": 11
    },
    {
        "name": "五福桥东路",
        "id": 14,
        "parentId": 9
    },
    {
        "name": "顺城大街",
        "id": 15,
        "parentId": 7
    },
    {
        "name": "浣花南路",
        "id": 16,
        "parentId": 8
    },
    {
        "name": "四川博物院",
        "id": 17,
        "parentId": 16
    },
    {
        "name": "草堂小学",
        "id": 18,
        "parentId": 16
    },
    {
        "name": "涪城区",
        "id": 19,
        "parentId": 3
    },
    {
        "name": "游仙区",
        "id": 20,
        "parentId": 3
    },
    {
        "name": "安州区",
        "id": 21,
        "parentId": 3
    }
]
构建树结构,并标记叶子结点
function buildTree(rawData) {
  // 可选。深拷贝不影响原始数据
  const data = JSON.parse(JSON.stringify(rawData));
  // 定义结果
  const result = [];
  // 初始化dataMap,将一维数组构造成以id为键的map对象
  const dataMap = {};
  data.forEach(item => {
    dataMap[item.id] = item;
    // 默认为叶子节点
    item.isLeaf = true;
    // 默认不存在子节点
    item.children = [];
  });
  // 遍历数组,构建树结构。注意,这里在循环中直接修改了data中的数据。
  data.forEach(item => {
    // 获取当前元素的父节点
    const parent = dataMap[item.parentId];
    if (parent) {
      // 父元素存在,标记父元素为非叶子节点。
      parent.isLeaf = false;
      // 将元素作为子节点插入父元素中
      parent.children.push(item);
    } else {
      // 父元素不存在,为根节点。判断是否存在子元素,标记叶子节点状态。
      // 这里标记叶子节点的时候,可能子元素还没插入到父元素中,结果标记为了叶子节点,但是上面的if判断成立,子元素会再标记一次这个根节点为非叶子节点。
      item.isLeaf = item.children.length === 0;
      // 父元素不存在,为根节点, 直接插入到result中。
      result.push(item);
    }
  });

  return result;
}

其他关注点

上述程序修改了原始数据,如果不想影响原始输入数据,可以通过loadsh的方法const data = lodash.cloneDeep(rawData)或者const data = JSON.parse(JSON.stringify(rawData))进行一次深拷贝。

代码的时间复杂度是2n,一个初始化数据的for循环,一个构建树结构的for循环。

如果原始数据已经标记了叶子节点的信息,就可以把代码中标记叶子节点的相关逻辑删掉了。

最后的输出结果
[
    {
        "name": "四川省",
        "id": 1,
        "parentId": null,
        "isLeaf": false,
        "children": [
            {
                "name": "成都市",
                "id": 2,
                "parentId": 1,
                "isLeaf": false,
                "children": [
                    {
                        "name": "锦江区",
                        "id": 7,
                        "parentId": 2,
                        "isLeaf": false,
                        "children": [
                            {
                                "name": "顺城大街",
                                "id": 15,
                                "parentId": 7,
                                "isLeaf": true,
                                "children": [
                                    
                                ]
                            }
                        ]
                    },
                    {
                        "name": "青羊区",
                        "id": 8,
                        "parentId": 2,
                        "isLeaf": false,
                        "children": [
                            {
                                "name": "浣花南路",
                                "id": 16,
                                "parentId": 8,
                                "isLeaf": false,
                                "children": [
                                    {
                                        "name": "四川博物院",
                                        "id": 17,
                                        "parentId": 16,
                                        "isLeaf": true,
                                        "children": [
                                            
                                        ]
                                    },
                                    {
                                        "name": "草堂小学",
                                        "id": 18,
                                        "parentId": 16,
                                        "isLeaf": true,
                                        "children": [
                                            
                                        ]
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "name": "金牛区",
                        "id": 9,
                        "parentId": 2,
                        "isLeaf": false,
                        "children": [
                            {
                                "name": "五福桥东路",
                                "id": 14,
                                "parentId": 9,
                                "isLeaf": true,
                                "children": [
                                    
                                ]
                            }
                        ]
                    },
                    {
                        "name": "武侯区",
                        "id": 10,
                        "parentId": 2,
                        "isLeaf": true,
                        "children": [
                            
                        ]
                    },
                    {
                        "name": "成华区",
                        "id": 11,
                        "parentId": 2,
                        "isLeaf": false,
                        "children": [
                            {
                                "name": "香木林路",
                                "id": 12,
                                "parentId": 11,
                                "isLeaf": true,
                                "children": [
                                    
                                ]
                            },
                            {
                                "name": "建工路",
                                "id": 13,
                                "parentId": 11,
                                "isLeaf": true,
                                "children": [
                                    
                                ]
                            }
                        ]
                    }
                ]
            },
            {
                "name": "绵阳市",
                "id": 3,
                "parentId": 1,
                "isLeaf": false,
                "children": [
                    {
                        "name": "涪城区",
                        "id": 19,
                        "parentId": 3,
                        "isLeaf": true,
                        "children": [
                            
                        ]
                    },
                    {
                        "name": "游仙区",
                        "id": 20,
                        "parentId": 3,
                        "isLeaf": true,
                        "children": [
                            
                        ]
                    },
                    {
                        "name": "安州区",
                        "id": 21,
                        "parentId": 3,
                        "isLeaf": true,
                        "children": [
                            
                        ]
                    }
                ]
            },
            {
                "name": "自贡市",
                "id": 4,
                "parentId": 1,
                "isLeaf": true,
                "children": [
                    
                ]
            },
            {
                "name": "泸州市",
                "id": 5,
                "parentId": 1,
                "isLeaf": true,
                "children": [
                    
                ]
            },
            {
                "name": "达州市",
                "id": 6,
                "parentId": 1,
                "isLeaf": true,
                "children": [
                    
                ]
            }
        ]
    }
]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值