1. 程式人生 > 其它 >如何將扁平陣列轉為樹形結構 實現O(n²)與O(n)時間複雜度的方案

如何將扁平陣列轉為樹形結構 實現O(n²)與O(n)時間複雜度的方案

/* 
    let arr = [
        { id: 1, name: '部門1', pid: 0 },
        { id: 2, name: '部門2', pid: 1 },
        { id: 3, name: '部門3', pid: 1 },
        { id: 4, name: '部門4', pid: 3 },
        { id: 5, name: '部門5', pid: 4 },
        { id: 6, name: '部門6', pid: 4666 },
    ]
    
    輸出結果:
        [
            {
                "id": 1,
                "name": "部門1",
                "pid": 0,
                "children": [
                    {
                        "id": 2,
                        "name": "部門2",
                        "pid": 1,
                        "children": []
                    },
                    {
                        "id": 3,
                        "name": "部門3",
                        "pid": 1,
                        "children": [
                            // 結果 ,,,
                        ]
                    }
                ]
            },
            {
                id: 6,
                name: '部門6',
                pid: 4666
            }
        ]

*/

/* 
    方案1 遞迴方式 
         先找出所有根節點,再找出所有根節點的子節點
         時間複雜度: O(n²)
*/
const getChildren = root => {
    root.children = arr.filter(v => v.pid === root.id)
    root.children.forEach(v => getChildren(v))
}
const transferTree = arr => {
    if (!Array.isArray(arr)) throw new Error('parameter arr must be Array.')
    if (arr.length === 1) return arr

    // 父子關係可以用map儲存
    const idMap = arr.reduce((total, cur) => Object.assign(total, { [cur.id]: { ...cur, children: [] } }), {})

    // 找出所有根節點
    const roots = arr.filter(node => !idMap[node.pid])

    // 找出根節點下面所有子節點
    roots.forEach(root => getChildren(root))

    return roots
}



/* 
    方案2 非遞迴方式
    時間複雜度: O(n)
*/
const transferTree2 = arr => {
    if (!Array.isArray(arr)) throw new Error('parameter arr must be Array.')
    if (arr.length === 1) return arr

    const res = []
    const idMap = arr.reduce((total, cur) => Object.assign(total, { [cur.id]: { ...cur, children: [] } }), {})
    for (const [, node] of Object.entries(idMap)) {
        // 根節點
        if (idMap[node.pid]) {
            res.push(node)
            continue;
        }
        // 子節點
        idMap[node.pid].children.push(node)
    }

    return res
}


console.log(transferTree2(arr))