JavaScript:四叉树比较

JavaScript: Quadtree comparison

我没有找到任何快速算法来获取以下格式的四叉树差异。 假设我们有两个任意的 4 级树:

var tree1 = [

    { id: "1.1", children: [

        { id: "1.1.1", children: null },
        { id: "1.1.2", children: null },
        { id: "1.1.3", children: [

            { id: "1.1.3.1", children: null },
            { id: "1.1.3.2", children: null },
            { id: "1.1.3.3", children: null },
            { id: "1.1.3.4", children: null }

        ] },
        { id: "1.1.4", children: null }

    ] },
    { id: "1.2", children: null },
    { id: "1.3", children: [

        { id: "1.3.1", children: [

            { id: "1.3.1.1", children: null },
            { id: "1.3.1.2", children: null },
            { id: "1.3.1.3", children: null },
            { id: "1.3.1.4", children: null }

        ] },
        { id: "1.3.2", children: null },
        { id: "1.3.3", children: null },
        { id: "1.3.4", children: null }

    ] },
    { id: "1.4", children: null }

];

var tree2 = [

  { id: "1.1", children: [

        { id: "1.1.1", children: null },
        { id: "1.1.2", children: null },
        { id: "1.1.3", children: null },
        { id: "1.1.4", children: [

            { id: "1.1.4.1", children: null },
            { id: "1.1.4.2", children: null },
            { id: "1.1.4.3", children: null },
            { id: "1.1.4.4", children: null }

        ] }

  ] },
  { id: "1.2", children: [

        { id: "1.2.1", children: null },
        { id: "1.2.2", children: null },
        { id: "1.2.3", children: [

            { id: "1.2.3.1", children: null },
            { id: "1.2.3.2", children: null },
            { id: "1.2.3.3", children: null },
            { id: "1.2.3.4", children: null }

        ] },
        { id: "1.2.1", children: null }

  ]},
  { id: "1.3", children: null },
  { id: "1.4", children: [

        { id: "1.4.1", children: [

            { id: "1.4.1.1", children: null },
            { id: "1.4.1.2", children: null },
            { id: "1.4.1.3", children: null },
            { id: "1.4.1.4", children: null }

        ] },
        { id: "1.4.2", children: null },
        { id: "1.4.3", children: null },
        { id: "1.4.1", children: null }

  ] }

];

所以,我需要找出不同点,return 它们是:

var result = {

    "1.1.3.1" : "1.1.3",
    "1.1.3.2" : "1.1.3",
    "1.1.3.3" : "1.1.3",
    "1.1.3.4" : "1.1.3",
    "1.1.4" : ["1.1.4.1", "1.1.4.2", "1.1.4.3", "1.1.4.4"],
    "1.2" : ["1.2.1", "1.2.2". ["1.2.3.1", "1.2.3.2", "1.2.3.3", "1.2.3.4"], "1.2.4"],
    "1.3.1.1" : "1.3",
    "1.3.1.2" : "1.3",
    "1.3.1.3" : "1.3",
    "1.3.1.4" : "1.3",
    "1.3.2" : "1.3",
    "1.3.3" : "1.3",
    "1.3.4" : "1.3",
    "1.4" : [["1.4.1.1", "1.4.1.2", "1.4.1.3", "1.4.1.4"], "1.4.2", "1.4.3", "1.4.4"]

 };

如果你能看到,结果必须是与更新对应的地图或字典。 不知道如何将 ["1.1.3.1", "1.1.3.2", "1.1.3.3", "1.1.3.4"] 引用到单个索引,所以我将它们分开,但是如果有更优雅的好的,不客气。

此数据为人工制作,如有错误请见谅。

您可以构建一棵树,在其中为树的 adding/deleting 部分添加标记 where,然后从中得出差异。

function getDifference(t1, t2) {

    function getD(object, parent) {
        function getKeys({ where, ...object }) {
            return Object.keys(object).flatMap(k => [k, ...(object[k] ? getKeys(object[k]) : [])]);
        }

        var types;

        Object
            .entries(object)
            .forEach(([k, { where, ...o }]) => {
                if (where) {
                    let keys = getKeys(o);
                    if (!types) types = {};
                    if (!types[where]) types[where] = [];
                    types[where].push(keys.length ? [k, keys] : k);
                } else {
                    getD(o, k);
                }
            });

        if (types) {
            if (-1 in types) result.push([types[-1], parent]);
            if (1 in types) result.push([parent, types[1]]);
        }
    }

    var temp = {},
        add = (inc, tree) => ({ id, children }) => {
            tree[id] = tree[id] || { where: 0 };
            tree[id].where += inc;
            if (children) children.forEach(add(inc, tree[id]));
        },
        result = [];

    t1.forEach(add(-1, temp));
    t2.forEach(add(1, temp));

    getD(temp);

    return result;
}    

var tree1 = [{ id: "1.1", children: [{ id: "1.1.1", children: null }, { id: "1.1.2", children: null }, { id: "1.1.3", children: [{ id: "1.1.3.1", children: null }, { id: "1.1.3.2", children: null }, { id: "1.1.3.3", children: null }, { id: "1.1.3.4", children: null }] }, { id: "1.1.4", children: null }] }, { id: "1.2", children: null }, { id: "1.3", children: [{ id: "1.3.1", children: [{ id: "1.3.1.1", children: null }, { id: "1.3.1.2", children: null }, { id: "1.3.1.3", children: null }, { id: "1.3.1.4", children: null }] }, { id: "1.3.2", children: null }, { id: "1.3.3", children: null }, { id: "1.3.4", children: null }] }, { id: "1.4", children: null }],
    tree2 = [{ id: "1.1", children: [{ id: "1.1.1", children: null }, { id: "1.1.2", children: null }, { id: "1.1.3", children: null }, { id: "1.1.4", children: [{ id: "1.1.4.1", children: null }, { id: "1.1.4.2", children: null }, { id: "1.1.4.3", children: null }, { id: "1.1.4.4", children: null }] }] }, { id: "1.2", children: [{ id: "1.2.1", children: null }, { id: "1.2.2", children: null }, { id: "1.2.3", children: [{ id: "1.2.3.1", children: null }, { id: "1.2.3.2", children: null }, { id: "1.2.3.3", children: null }, { id: "1.2.3.4", children: null }] }, { id: "1.2.4", children: null }] }, { id: "1.3", children: null }, { id: "1.4", children: [{ id: "1.4.1", children: [{ id: "1.4.1.1", children: null }, { id: "1.4.1.2", children: null }, { id: "1.4.1.3", children: null }, { id: "1.4.1.4", children: null }] }, { id: "1.4.2", children: null }, { id: "1.4.3", children: null }, { id: "1.4.4", children: null }] }],
    result = getDifference(tree1, tree2);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }