还原二叉树

197 阅读1分钟

tree结构:

从前有颗tree长这样👇,现在需要把它拍平成一维数组,然后,再还原成这颗tree原本的模样:

let tree = {
    name: 1,
    children: [
        {
            name: 2,
            children: [
                {
                    name: 4,
                    children: [
                        {
                            name: 7,
                            children: []
                        }
                    ]
                },
                {
                    name: 5,
                    children: []
                }
            ]
        },
        {
            name: 3,
            children: [
                {
                    name: 6,
                    children: []
                }
            ]
        }
    ]
}

一维数组结构

// 拍平成一维数组,需要能够保存tree的依赖关系,以便能够还原。
// 在手动开始解题之前,应该先设计好想要生成的数据结构,我一开始也没做到... 切记思考比一上来就写代码更重要哇!
// eg.我想生成的一维数组的数据结构长这样👇
var arr = [
    {
        name: 1,
        parent: null,
        children: [2, 3]
    },
    {
        name: 2,
        parent: 1,
        children: [4, 5]
    },
    {
        name: 4,
        parent: 2,
        children: [7]
    },
    {
        name: 7,
        parent: 4,
        children: []
    },
    {
        name: 5,
        parent: 2,
        children: []
        },
        {
            name: 3,
            parent: 1,
            children: [6]
        },
        {
            name: 6,
            parent: 3,
            children: []
        }
    ];

二叉树变一维数组

//那么,如何把tree变成更上面这样的结构呢?先尝试用最简单的二叉树前序遍历的方式来做,比较容易理解😊:
function traverse(tree) {
    let res = [];
    function walk(node, parent=null) { 
        let children = node.children;
        let obj = {
            name: node.name,
            parent,
            children: children.map(child => child.name) || []
        }
        res.push(obj);
        if (children.length) {
            children.forEach(child => {
                walk(child, node.name) // 递归调用walk
            })
        }
    }
    walk(tree);
    return res;
}

let oneDimension = traverse(tree);

还原二叉树

// 接下来,从一维数组oneDimension还原成tree:
function revert(arr) {
    let root = arr.shift();
    function r(node) {
        console.log('node!!!', node);
        delete node.parent;
        node.children = node.children.length ? node.children.map(child => {
            let item = arr.find(item => item.name === child);
            return {
                name: child,
                children: r(item)
            }
        }) : [];
        return node.children;
    }
    r(root)
    return root;
}
revert(oneDimension);

// 可以发现,parent并没有用上,但我又觉得parent其实有必要存在,所以没有去掉这个属性。想想parent的应用场景🤔