几天前,应项目的要求开发了一个新的树控件.使用后,开发人员反应良好,效率有了质的提升. 其中一个核心算法如下:
_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!
效率基本接*是线性了. 哈.. 还能再改进吗? 大拿们.