Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
快速稳定排序算法的javascript实现_Javascript_Algorithm_Sorting - Fatal编程技术网

快速稳定排序算法的javascript实现

快速稳定排序算法的javascript实现,javascript,algorithm,sorting,Javascript,Algorithm,Sorting,我希望对大约200-300个对象的数组进行排序,根据特定键和给定顺序(asc/desc)进行排序。结果的顺序必须是一致和稳定的 使用哪种算法最好,您能提供一个javascript实现的示例吗 谢谢 因为您正在寻找稳定的东西,所以合并排序应该可以 代码可在上述网站上找到: function mergeSort(arr) { if (arr.length < 2) return arr; var middle = parseInt(arr.length /

我希望对大约200-300个对象的数组进行排序,根据特定键和给定顺序(asc/desc)进行排序。结果的顺序必须是一致和稳定的

使用哪种算法最好,您能提供一个javascript实现的示例吗


谢谢

因为您正在寻找稳定的东西,所以合并排序应该可以

代码可在上述网站上找到:

function mergeSort(arr)
{
    if (arr.length < 2)
        return arr;

    var middle = parseInt(arr.length / 2);
    var left   = arr.slice(0, middle);
    var right  = arr.slice(middle, arr.length);

    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right)
{
    var result = [];

    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift());
        } else {
            result.push(right.shift());
        }
    }

    while (left.length)
        result.push(left.shift());

    while (right.length)
        result.push(right.shift());

    return result;
}
函数合并排序(arr)
{
如果(arr.length<2)
返回arr;
var middle=parseInt(arr.length/2);
var left=arr.slice(0,中间);
var right=arr.slice(中间,arr.length);
返回merge(mergeSort(左)、mergeSort(右));
}
函数合并(左、右)
{
var结果=[];
while(left.length&&right.length){

如果(左[0],则可以从非稳定排序函数获得稳定排序

在排序之前,您将获得所有元素的位置。 在排序条件下,如果两个元素相等,则按位置排序

function stableSort(arr, cmpFunc) {
    //wrap the arr elements in wrapper objects, so we can associate them with their origional starting index position
    var arrOfWrapper = arr.map(function(elem, idx){
        return {elem: elem, idx: idx};
    });

    //sort the wrappers, breaking sorting ties by using their elements orig index position
    arrOfWrapper.sort(function(wrapperA, wrapperB){
        var cmpDiff = cmpFunc(wrapperA.elem, wrapperB.elem);
        return cmpDiff === 0 
             ? wrapperA.idx - wrapperB.idx
             : cmpDiff;
    });

    //unwrap and return the elements
    return arrOfWrapper.map(function(wrapper){
        return wrapper.elem;
    });
}
塔达!你有一个稳定的类型


如果您想更多地了解这项技术以及如何实现它,我已经在我的博客上写了一篇关于它的文章:

计数排序比合并排序快(它在O(n)时间内执行),并且用于整数

Math.counting_sort = function (m) {
    var i
    var j
    var k
    var step
    var start
    var Output
    var hash
    k = m.length
    Output = new Array ()
    hash = new Array ()
    // start at lowest possible value of m
    start = 0
    step = 1
    // hash all values
    i = 0
    while ( i < k ) {
        var _m = m[i]
        hash [_m] = _m
        i = i + 1
    }
    i = 0
    j = start
    // find all elements within x
    while ( i < k ) {
        while ( j != hash[j] ) {
            j = j + step
        }
        Output [i] = j
        i = i + 1
        j = j + step
    }
    return Output
}
Math.counting\u sort=函数(m){
变量i
var j
变量k
变步长
var启动
无功输出
var散列
k=米长
输出=新数组()
哈希=新数组()
//从最低可能值m开始
开始=0
步骤=1
//散列所有值
i=0
而(i
例如:

var uArray = new Array ()<br/>
var sArray = new Array ()<br/><br/>
uArray = [ 10,1,9,2,8,3,7,4,6,5 ]<br/>
sArray = Math.counting_sort ( uArray ) // returns a sorted array
var uArray=new数组()
var sArray=新数组()

uArray=[10,1,9,2,8,3,7,4,6,5]
sArray=Math.counting\u sort(uArray)//返回已排序的数组
我知道这个问题已经回答了一段时间了,但我的剪贴板中正好有一个很好的用于Array和jQuery的稳定合并排序实现,所以我将与大家分享,希望将来的搜索者会发现它很有用

它允许您指定自己的比较函数,就像普通的
Array.sort
实现一样

实施
//向数组和jQuery原型添加稳定的合并排序
//注意:我们将其封装在一个封闭的容器中,这样它就不会污染全球环境
//名称空间,但我们没有将其放在$(document).ready中,因为它是
//不依赖于DOM
(功能(){
//向数组和jQuery公开
Array.prototype.mergeSort=jQuery.fn.mergeSort=mergeSort;
函数合并排序(比较){
var length=这个.length,
中间=数学楼层(长度/2);
如果(!比较){
比较=功能(左、右){
if(左<右)
返回-1;
如果(左==右)
返回0;
其他的
返回1;
};
}
如果(长度<2)
归还这个;
返回合并(
此.slice(0,中间).mergeSort(比较),
this.slice(中间,长度).mergeSort(比较),
比较
);
}
函数合并(左、右、比较){
var结果=[];
while(left.length>0 | | right.length>0){
if(left.length>0&&right.length>0){
if(比较(左[0],右[0])0){
结果。推(左[0]);
左=左。切片(1);
}
否则如果(右。长度>0){
结果.推送(右[0]);
右=右。切片(1);
}
}
返回结果;
}
})();
示例用法
var排序=[
“手指”,
“三明治”,
“三明治”,
"五块猪皮",,
“一个叫史蒂夫的家伙”,
“一些面条”,
“拖把和扫帚”,
“薯片品牌®薯片”
].mergeSort(函数(左、右){
lval=left.toLowerCase();
rval=right.toLowerCase();
console.log(lval、rval);
如果(左心室<右心室)
返回-1;
else if(lval==rval)
返回0;
其他的
返回1;
});
排序==[“5块猪皮”、“一个叫史蒂夫的家伙”、“手指”、“拖把和扫帚”、“薯片品牌®薯片”、“三明治”、“三明治”、“一些面条”];

var a=[34203,37462009848198764,9];
函数合并排序(arr)
{
如果(arr.length<2)
返回arr;
var middle=parseInt(arr.length/2);
var left=arr.slice(0,中间);
var right=arr.slice(中间,arr.length);
返回merge(mergeSort(左)、mergeSort(右));
}
函数合并(左、右)
{
var结果=[];
while(left.length&&right.length){

if(left[0]这是一个稳定的实现。它通过使用本机排序来工作,但在元素比较相等的情况下,您可以使用原始索引位置打破联系

function stableSort(arr, cmpFunc) {
    //wrap the arr elements in wrapper objects, so we can associate them with their origional starting index position
    var arrOfWrapper = arr.map(function(elem, idx){
        return {elem: elem, idx: idx};
    });

    //sort the wrappers, breaking sorting ties by using their elements orig index position
    arrOfWrapper.sort(function(wrapperA, wrapperB){
        var cmpDiff = cmpFunc(wrapperA.elem, wrapperB.elem);
        return cmpDiff === 0 
             ? wrapperA.idx - wrapperB.idx
             : cmpDiff;
    });

    //unwrap and return the elements
    return arrOfWrapper.map(function(wrapper){
        return wrapper.elem;
    });
}
不彻底的测试

var res = stableSort([{a:1, b:4}, {a:1, b:5}], function(a, b){
    return a.a - b.a;
});
console.log(res);
暗示了这一点,但没有发布给codez


但是,根据我的说法,它并不快。我修改了a以接受自定义比较器函数,而且速度更快。

我必须按任意列对多维数组进行排序,然后再按另一列进行排序。我使用此函数对:

function sortMDArrayByColumn(ary, sortColumn){

    //Adds a sequential number to each row of the array
    //This is the part that adds stability to the sort
    for(var x=0; x<ary.length; x++){ary[x].index = x;}

    ary.sort(function(a,b){
        if(a[sortColumn]>b[sortColumn]){return 1;}
        if(a[sortColumn]<b[sortColumn]){return -1;}
        if(a.index>b.index){
            return 1;
        }
        return -1;
    });
}
函数sortMDArrayByColumn(ary,sortColumn){
//将序列号添加到数组的每一行
//这是增加排序稳定性的部分
对于(var x=0;xb[sortColumn]){return 1;}
if(a[sortColumn]b.索引){
返回1;
}
返回-1;
});
}
请注意,ari.sort从不返回零,这是“sort”函数的一些实现做出可能不正确决定的地方


这也非常快。

您也可以使用Timsort。这是一个非常复杂的算法(400多行,因此这里没有源代码),因此请查看或使用现有的Java之一
var res = stableSort([{a:1, b:4}, {a:1, b:5}], function(a, b){
    return a.a - b.a;
});
console.log(res);
function sortMDArrayByColumn(ary, sortColumn){

    //Adds a sequential number to each row of the array
    //This is the part that adds stability to the sort
    for(var x=0; x<ary.length; x++){ary[x].index = x;}

    ary.sort(function(a,b){
        if(a[sortColumn]>b[sortColumn]){return 1;}
        if(a[sortColumn]<b[sortColumn]){return -1;}
        if(a.index>b.index){
            return 1;
        }
        return -1;
    });
}
(a, b) => { 
  /* some way to compare a and b, returning -1, 0, or 1 */ 
};
(i, j) => { 
  let a = arrayToBeSorted[i], b = arrayToBeSorted[j]; 
  /* some way to compare a and b, returning -1 or 1 */
  return i - j; // fallback when a == b
}
/**
 * - `array`: array to be sorted
 * - `comparator`: closure that expects indices `i` and `j`, and then
 *   compares `array[i]` to `array[j]` in some way. To force stability,
 *   end with `i - j` as the last "comparison".
 * 
 * Example:
 * ```
 *  let array = [{n: 1, s: "b"}, {n: 1, s: "a"}, {n:0, s: "a"}];
 *  const comparator = (i, j) => {
 *    const ni = array[i].n, nj = array[j].n;
 *    return ni < nj ? -1 :
 *      ni > nj ? 1 :
 *        i - j;
 *  };
 *  stableSortInPlace(array, comparator);
 *  // ==> [{n:0, s: "a"}, {n:1, s: "b"}, {n:1, s: "a"}]
 * ```
 */
function stableSortInPlace(array, comparator) {
  return sortFromIndices(array, findIndices(array, comparator));
}

function stableSortedCopy(array, comparator){
  let indices = findIndices(array, comparator);
  let sortedArray = [];
  for (let i = 0; i < array.length; i++){
    sortedArray.push(array[indices[i]]);
  }
  return sortedArray;
}

function findIndices(array, comparator){
  // Assumes we don't have to worry about sorting more than 
  // 4 billion elements; if you know the upper bounds of your
  // input you could replace it with a smaller typed array
  let indices = new Uint32Array(array.length);
  for (let i = 0; i < indices.length; i++) {
    indices[i] = i;
  }
  // after sorting, `indices[i]` gives the index from where
  // `array[i]` should take the value from, so to sort
  // move the value at at `array[indices[i]]` to `array[i]`
  return indices.sort(comparator);
}

// If I'm not mistaken this is O(2n) - each value is moved
// only once (not counting the vacancy temporaries), and 
// we also walk through the whole array once more to check
// for each cycle.
function sortFromIndices(array, indices) {
  // there might be multiple cycles, so we must
  // walk through the whole array to check.
  for (let k = 0; k < array.length; k++) {
    // advance until we find a value in
    // the "wrong" position
    if (k !== indices[k]) {
      // create vacancy to use "half-swaps" trick,
      // props to Andrei Alexandrescu
      let v0 = array[k];
      let i = k;
      let j = indices[k];
      while (j !== k) {
        // half-swap next value
        array[i] = array[j];
        // array[i] now contains the value it should have,
        // so we update indices[i] to reflect this
        indices[i] = i;
        // go to next index
        i = j;
        j = indices[j];
      }
      // put original array[k] back in
      // and update indices
      array[i] = v0;
      indices[i] = i;
    }
  }
  return array;
}
function stableSort(arr, compare) {
    var original = arr.slice(0);

    arr.sort(function(a, b){
        var result = compare(a, b);
        return result === 0 ? original.indexOf(a) - original.indexOf(b) : result;
    });

    return arr;
}
var stableSort = (arr, compare) => arr
  .map((item, index) => ({item, index}))
  .sort((a, b) => compare(a.item, b.item) || a.index - b.index)
  .map(({item}) => item)
stableSort([5,6,3,2,1], (a, b) => a - b)
// sorted by weight
var input = [
  { height: 100, weight: 80 },
  { height: 90, weight: 90 },
  { height: 70, weight: 95 },
  { height: 100, weight: 100 },
  { height: 80, weight: 110 },
  { height: 110, weight: 115 },
  { height: 100, weight: 120 },
  { height: 70, weight: 125 },
  { height: 70, weight: 130 },
  { height: 100, weight: 135 },
  { height: 75, weight: 140 },
  { height: 70, weight: 140 }
]
stableSort(input, (a, b) => a.height - b.height)
// Items with the same height are still sorted by weight 
// which means they preserved their relative order.
var stable = [
  { height: 70, weight: 95 },
  { height: 70, weight: 125 },
  { height: 70, weight: 130 },
  { height: 70, weight: 140 },
  { height: 75, weight: 140 },
  { height: 80, weight: 110 },
  { height: 90, weight: 90 },
  { height: 100, weight: 80 },
  { height: 100, weight: 100 },
  { height: 100, weight: 120 },
  { height: 100, weight: 135 },
  { height: 110, weight: 115 }
]
input.sort((a, b) => a.height - b.height)
var unstable = [
  { height: 70, weight: 140 },
  { height: 70, weight: 95 },
  { height: 70, weight: 125 },
  { height: 70, weight: 130 },
  { height: 75, weight: 140 },
  { height: 80, weight: 110 },
  { height: 90, weight: 90 },
  { height: 100, weight: 100 },
  { height: 100, weight: 80 },
  { height: 100, weight: 135 },
  { height: 100, weight: 120 },
  { height: 110, weight: 115 }
]