节点排序 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;

          }

        }

你可能感兴趣的:(排序)