一个算法改进带来惊人效率

几天前,应项目的要求开发了一个新的树控件.使用后,开发人员反应良好,效率有了质的提升. 其中一个核心算法如下:

    _generate_tree: function(pnode, items) {
        if (items.length === 0) return;
        var item, node, id, text, pid, level, checked;
        for (var i = items.length - 1; i >= 0; i--) {
            item = items[i];
            pid = item["parentid"];
            if (pid === pnode.id) {
                id = item["id"];
                text = item["text"];
                level = pnode["level"] + 1;
                checked = item["checked"];
                node = new Node(id, pnode, text, level, checked);
                pnode.add(node);
    
                this.nodes[id] = node;
                this.dataset[id] = item;
    
                items = items.slice(0);
                items.splice(i, 1);
                arguments.callee.call(this, node, items);
	    }
        }
   }
        
    

用于生成树的存储结构如下:

[{"id":"1","parentid":"0","text":"全网组织"},{"id":"58","parentid":"1","text":"asdfasdfdsa"},{"id":"2","parentid":"1","text":"商户组织"},{"id":"3","parentid":"1","text":"用户组织"},{"id":"4","parentid":"1","text":"运维部"},{"id":"64","parentid":"2","text":"nnnnn"},{"id":"65","parentid":"2","text":"vvvvv"},{"id":"63","parentid":"2","text":"mmmmm"},{"id":"55","parentid":"2","text":"vwfwefwef"},{"id":"61","parentid":"2","text":"tetetetetet"},{"id":"23","parentid":"2","text":"testtest"},{"id":"25","parentid":"2","text":"劳而无功"},{"id":"47","parentid":"2","text":"1313"},{"id":"46","parentid":"2","text":"12"},{"id":"48","parentid":"2","text":"14"},{"id":"43","parentid":"2","text":"5678"}]

备注:用于生成树的存储结构是无序的.node是树的一个节点,有相应的属性及方法.
这个构造树的函数可以很好的工作,思路也清晰明了.只是效率是 n! ,接**方级.
一般现实使用中,用于生成树的数据都不会很多;很多的话,都是采用点击异步加载的方式来实现. 所以,测试人员也没有提出意见.
我在作代码审查的时候,作了一个性能测试.用2000多条记录生成一个树.
chrome下表现尚可, 稳定在160ms左右;在ie7,则达到了4s左右.OMG,这个简直无法令人接受.
深思熟虑后,提供了一个改进后的算法.

    _generate_tree2: function(root, items) {
        if (items.length === 0) return;
        var self = this;
        var item, node, id, text, pid,rid = root.id, level, checked,dict = {};
    
        for (var i = items.length - 1; i >= 0; i--) {
            item = items[i];
            pid = item["parentid"];
            if( !dict[pid] ){
                dict[pid] = [];
            }
            dict[pid].push(item);
        (function(pid,pnode) {
            var cs = dict[pid];
            if(!cs) return;
            for (var j = 0; j < cs.length; j++) {
                item = cs[j];
                id = item["id"];
                text = item["text"];
                level = pnode["level"] + 1;
                checked = item["checked"];
                node = new Node(id, pnode, text, level, checked);
                pnode.add(node);
                self.nodes[id] = node;
                self.dataset[id] = item;
                arguments.callee.call(self, node.id, node);
            
        })(rid,root);
     }
    

这次测试后,在chrome下稳定在4ms左右,在ie7下则稳定在60ms左右.so perfect!
效率基本接*是线性了. 哈.. 还能再改进吗? 大拿们.

原文地址:https://www.cnblogs.com/ms_config/p/2124997.html