zoukankan      html  css  js  c++  java
  • 节点排序 2

    对支持sourceIndex的HTML文档的节点重排,使用JK提供的思路,速度至少比单纯使用nodes.sort(function(a,b){return a.sourceIndex - b.sourceIndex})这种方式快两倍:

    //灵感来自
    //http://www.cnblogs.com/jkisjk/archive/2011/01/28/array_quickly_sortby.html
            var hasDuplicate = false;
            var sortBy = function(nodes){
              var result = [], array = [], n = nodes.length, i = n, node;
              while(node = nodes[--n]){
                (array[n] = new Number(~~node.sourceIndex))._ = node;
              }
              array.sort(function(a,b){
                if(a === b) hasDuplicate = true;
                return a - b ;
              });
              while( i )
                result[--i] = array[i]._;
              return result;
            }
    

    但标准浏览器不支持这属性,在IE中,XML文档也没有此属性,这时就需要跟据节点的parentNode与nextSibling,但如果单单是两两比较,速度是提升不了的。因此我们就转而比较最近公共祖先的孩子们的顺序了。这时,算法的威力就体现出来了。这是第一版,根据某一朋友提供的LCA搞出来的东西,当然大体思路还是归功于JK大神。但实际效果不如意,比jQuery的那个sortOrder慢,估计问题出在求LCA上。

    //根据这里JK提供的思路
    //http://www.cnblogs.com/rubylouvre/archive/2011/01/28/1947286.html#2020900
    var tick = 0, hasDuplicate = false;
    var Rage = {
    //form http://www.cnblogs.com/GrayZhang/archive/2010/12/29/find-closest-common-parent.html
    	getLCA:function(nodes){
    		var hash = {}, i = 0,
    			attr = "data-find"+(++tick),
    			length = nodes.length,
    			node,
    			parent,
    			counter = 0,
    			uuid;
    		while(node = nodes[i++]){
    			parent = node;
    			while(parent){
    				if(parent.nodeType === 1){
    					break;
    				}
    				uuid = parent.getAttribute(attr);
    				if(!uuid){
    					uuid = "_" + (++counter);
    					parent.setAttribute(attr,uuid);
    					hash[uuid] = {node:parent,count:1};
    				}else{
    					hash[uuid].count ++;
    				}
    				parent = parent.parentNode;
    			}
    		}
    		for(var i in hash){
    			if(hash[i].count === length){
    				return hash[i].node;
    			}
    		}
    	},
    	getList : function(nodes,parent){//获取当前元素到最近公共祖先间的所有祖先,包括自己
    		var list = [];
    		while(node){
    			if(node === parent){
    				break;
    			}
    			list.unshift(node);
    			node = node.parentNode;
    		}
    		return list;
    	},
    	getLists : function(){
    		var lists = [], getList = Rage.getList, i=0, node, list;
    		while(node = nodes[i++]){
    			list = getList(node,parent);
    			if(list.length){
    				lists[ lists.length ] = list;
    		    }
    		}
    		return lists;
    	},
             sortList : function(a,b){
                var n = Math.min(a.length,b.length),ap,bp;
                for(var i=0; i < n; i++){
                  ap = a[i],bp = b[i]
                  if(ap !== bp){
                    while(ap = ap.nextSibling){
                      if(ap === bp){
                        return -1
                      }
                    }
                    return 1
                  }
                }
                return a.length-b.length;
         },
        uniqueSort : function(nodes){
        	var length = nodes.length;
        	var LCA = Rage.getLCA(nodes);
        	var lists = Rage.getLists(nodes,LCA);
        	lists.sort(Rage.sortList);
        	var list, i = 0, result = [];
        	while(list = lists[i++]){
        		result[result.length] list.pop();
        	}
        	if(result.length !== length){
        		result.unshift(LAC);
        		if(result.length != length){
        			hasDuplicate = true;
        		}
        	}
        	return result;
        }
    }
    

    下面是第二版,经过改进,终于比jQuery的那个快上三倍(测试对象为拥有260多个节点的文档)

            var hasDuplicate = false;
            var Rage = {
    
              getList : function(node){
                var list = [];
                while(node){
                  if(node.nodeType === 9){
                    break;
                  }
                  list.unshift(node);
                  node = node.parentNode;
                }
                return list;
              },
              getLists : function(nodes){
                var lists = [], getList = Rage.getList, i=0, node;
                while(node = nodes[i++]){
                  lists[ lists.length ] = getList(node);
                }
                return lists;
              },
              sliceList : function(lists,num){
                var result = [], i = 0, list;
                while(list = lists[i++]){
                  list = list.slice(num);
                  if(list.length){
                    result[ result.length ] = list;
                  }
                }
                return result;
              },
              sortList : function(a,b){
                var n = Math.min(a.length,b.length),ap,bp;
                for(var i=0; i < n; i++){
                  ap = a[i],bp = b[i]
                  if(ap !== bp){
                    while(ap = ap.nextSibling){
                      if(ap === bp){
                        return -1
                      }
                    }
                    return 1
                  }
                }
                return a.length-b.length;
              },
              uniqueSort : function(nodes){
                var length = nodes.length;
                var lists = Rage.getLists(nodes);
                lists.sort(function(a,b){
                  return a.length - b.length;
                });
                var depth = lists[0].length, length = lists.length, parent, cut, ii = 0;
                for(var i =0; i < depth; i++){
                  parent = lists[0][i];
                  cut = true;
                  for(var j = 1;j <  length; j++){
                    if(parent !== lists[j][i]){
                      cut = false;
                      break;
                    }
                  }
                  if(cut){
                    ii++
                  }else{
                    break;
                  }
                }
                var LCA = lists[0][ii-1];
                lists = Rage.sliceList(lists,ii);
                lists.sort(Rage.sortList);
                var list, i = 0, result = [];
                while(list = lists[i++]){
                  result[result.length] = list.pop();
                }
                 
                if(result.length !== length){
                  result.unshift(LCA);
                  if(result.length != length){
                    hasDuplicate = true;
                  }
                }
                return result;
              }
            }
    
  • 相关阅读:
    iPhone控件之UIWebView2
    Xcode 4.1/4.2 免证书(iDP)开发+真机调试
    iPhone控件之UIToolbar
    POJ 2472 ||SDUT 2358 106 miles to Chicago(Dijkstra算法变形)
    POJ 2418 Hardwood Species(二叉排序树)
    POJ 2513 Colored Sticks(字典树 + 并查集 + 欧拉回路)
    HDU 4033 Regular Polygon(几何 + 二分)
    POJ 3191 The Moronic Cowmpouter(二进制的变形)
    POJ 2442 Sequence(堆的应用)
    HDU 4036 Rolling Hongshu(数学+物理应用)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1947901.html
Copyright © 2011-2022 走看看