基于两个属性

时间:2017-04-13 05:50:05

标签: javascript algorithm sorting recursion

我有一棵这样的树:

var children = [
    {
        label: 'Foo',
        children: [ ... ]
    }
    ...
];

我需要用两个约束对它进行排序:

  1. 有孩子的节点排在第一位并自行分类
  2. 没有孩子的节点排在第二位并自行排序
  3. 只要孩子的数量大于0,孩子的数量就无关紧要了。

    所以,如果原始树像这样表示:

    Foo.0
    Sou.2
        Zorro.0
        Amba.0
    Book.0
    Bud.1
        Ram.0
    

    排序时看起来像这样:

    Bud.1
        Ram.0
    Sou.2
        Amba.0
        Zorro.0
    Book.0
    Foo.0
    

    所以,我想出了两个递归解决方案:

    第一个只是应用内置排序功能:

    function sortFn(a, b) {
        var aHasChildren = a.children.length,
            bHasChildren = b.children.length;
    
        if (aHasChildren && bHasChildren || !aHasChildren && !bHasChildren) {
            return a.label.localeCompare(b.label);
        } else {
            return aHasChildren ? -1 : 1;
        }
    }
    
    function sortNodesAndChildren(nodes) {
        return nodes
            .sort(sortFn)
            .forEach(function (node) {
                if (node.children.length) {
                    sortNodesAndChildren(node.children);
                }
            })
    }
    

    第二个使用按排序顺序保存的其他数组,并使用线性插入排序将元素插入到这些数组中:

    function sort(nodes) {
        var a = [];
        var b = [];
    
        nodes.forEach(function (node) {
            if (node.children.length === 0) {
                insert(a, node);
            } else {
                insert(b, node);
                node.children = sort(node.children);
            }
        });
    
        return b.concat(a);
    }
    
    
    function insert(a, o, property) {
        for (var i = 0; i < a.length; i++) {
            if (o.label.localeCompare(a[i].label) === -1) {
                a.splice(i, 0, o);
                return;
            }
        }
    
        a.push(o);
    }
    

    第二个实现在jsperf中显示了相当差的结果。但我认为应该使用复杂性而不是性能来比较它们。所以我有两个问题:

    1. 第二种实现在算法复杂性方面是否更糟?
    2. 除了我提出的目标之外,还有更好的方法来完成任务吗?

0 个答案:

没有答案