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;
              }
            }
    
  • 相关阅读:
    Understanding about Baire Category Theorem
    Isometric embedding of metric space
    Convergence theorems for measurable functions
    Mindmap for "Principles of boundary element methods"
    Various formulations of Maxwell equations
    Existence and uniqueness theorems for variational problems
    Kernels and image sets for an operator and its dual
    [loj6498]农民
    [luogu3781]切树游戏
    [atAGC051B]Three Coins
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1947901.html
Copyright © 2011-2022 走看看