javascript 节点排序 2

复制代码 代码如下:

  //灵感来自

  //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;

  }

  }