使用单个更新对有序列表中的元素重新排序

时间:2013-11-05 17:27:35

标签: javascript algorithm sorting

假设我有一个按其元素的priority属性排序的列表,这是一个数字。我知道列表中每个成员的priority值,但我想将一个元素移动到特定索引。是否可以通过仅修改我想要移动的元素的priority来实现此目的?

priority不一定是整数。任何算法都可用于确定元素priority需要的内容,但priority必须是唯一的。

我认为在所需索引之前和之后获取元素的priority,但我不知道如何在它们之间选择一个最终不会导致重复的数字。如果我之前只为元素添加一些给定值(整数或十进制),我最终会获得与之后元素相同的值。使用两者之间的范围调用random()会起作用,但这似乎是真正迂回的做事方式。

如果这种操作有名字,我也有兴趣学习它。

2 个答案:

答案 0 :(得分:1)

值m =(大+低)/ 2总是在两个值的中间。

有关编号的进一步阅读,请参阅讲座: http://www.cs.uni-paderborn.de/fachgebiete/ag-boettcher/lehre/ss2012/dbis-2/download.html

答案 1 :(得分:1)

  

(上/下)/ 2怎么样?

在@msander的答案上扩展一下,您可以使用字母数字优先级来确保始终具有“中间”优先级来分配。如果你需要分配许多优先级,两个连续优先级之间的距离会越来越低,最终会失去精度,你会得到像((上+下)/ 2 ===更低)。

如果您更改获得中间优先级的方式,则可以使用字符串(不会丢失精度),而不是实际数字。例如,如果您的优先级是字符串式数字(由0,1,2,3,4,5,6,7,8,9组成的字符串):

['1','3','4']

在1到3之间移动4将导致: ['1','2','3']

在2和1之间移动3将导致: ['1','15','2']

在1到15之间移动2将导致: ['1','12','15']

您需要注意的是如何比较优先级(String.prototype.localeCompare)。

同样,如果您希望在精确丢失方面遇到麻烦,这个解决方案是值得的。

编辑(添加了计算优先级的函数):

免责声明:代码出乎意料地难以理解。如果有人有更好的想法,请随意插入。如果你只使用二进制字符串(只包含0和1的字符串),它将更容易编写。

function getMiddlePriority(p1, p2) {
  var i=0,result = '';

  // The identical digits need to be in the result
  while ((p1[i] || '0') === (p2[i] || '0')) {
    result += p1[i++] || '0';
  }

  // First different digit p1[i] !== p2[i]

  // if the digits are far enough apart, there is a number between them
  if ((p2[i]||0) - (p1[i]||0) > 1) {
    return result + Math.floor(((+p2[i]||0) + (+p1[i]||0))/2);
  }

  // p2[i] === p1[i]+1

  // Digits are close, need to parse some more digits to get a number between
  var first = i++;
  var k = 0;
  while ((p1[i] === '9') && ((p2[i]||'0') === '0')) {
    i++; 
    k++;
  }


  // p[i] is not 9 or p2[i] is not 0/undefined
  if (p1[i] === '9') {
    result += (p2[first]||'0')  + repeat('0', k);
    result += p2[i] === '1' ? '05' : Math.floor(p2[i]/2);
  } else {
    result += (p1[first]||'0') + repeat('9', k);
    result += Math.floor((10 + (+p1[i] || 0))/2);
  } 

  return result;
}


function repeat(character, count) {
  var s = '';
  while (count--) s+= character;
  return s;
}


console.clear();
console.log('Expected 2 Got ' + getMiddlePriority('1', '3'));
console.log('Expected 25 Got ' + getMiddlePriority('2', '3'));
console.log('Expected 22 Got ' + getMiddlePriority('2', '25'));
console.log('Expected 21 Got ' + getMiddlePriority('2', '22'));
console.log('Expected 205 Got ' + getMiddlePriority('2', '21'));
console.log('Expected 202 Got ' + getMiddlePriority('2', '205'));
console.log('Expected 215 Got ' + getMiddlePriority('21', '22'));
console.log('Expected 1055 Got ' + getMiddlePriority('105', '106'));
console.log('Expected 10995 Got ' + getMiddlePriority('1099', '11'));
console.log('Expected 1105 Got ' + getMiddlePriority('1099', '111'));

字符串优先级的替代方法是使用数字优先级,并且每隔一段时间(当(upper+lower)/2 === lower || (upper+lower)/2 === upper时)重新分配优先级。当然这不适合这个问题,因为对于N次重新排序,您不会进行1次更新,但是1+ N/S会更新,其中S是在用完可用优先级之前可以执行的更新量。至少它是一个正确的解决方案(优先级永远是唯一的)。