JavaScript快速排序中的无限递归?

JavaScript快速排序中的无限递归?,javascript,algorithm,sorting,quicksort,Javascript,Algorithm,Sorting,Quicksort,这是我写的代码。函数无法工作,因为它无法到达基本情况。如果我将pivot、r和l记录到控制台,则无论调用排序函数多少次,它们都保持不变。所以我想知道参数l,r是否真的作为数据传递到函数中。为什么会这样 function sort(data){ if(data.length < 2){ return data; } else{ var l = []; var r = []; var pivot = par

这是我写的代码。函数无法工作,因为它无法到达基本情况。如果我将pivot、
r
l
记录到控制台,则无论调用排序函数多少次,它们都保持不变。所以我想知道参数
l
r
是否真的作为数据传递到函数中。为什么会这样

function sort(data){
    if(data.length < 2){
        return data;
    }
    else{
        var l = [];
        var r = [];
        var pivot = parseInt(data.length/2);
        for(i=0; i<data.length; i++){
            if(data[i] > data[pivot]){
                r.push(data[i]);
            }
            else{
                l.push(data[i]);
            }
        }
        return sort(l).concat(sort(r));
    }
}
函数排序(数据){
如果(数据长度<2){
返回数据;
}
否则{
var l=[];
var r=[];
var pivot=parseInt(data.length/2);
对于(i=0;i数据[pivot]){
r、 推送(数据[i]);
}
否则{
l、 推送(数据[i]);
}
}
返回排序(l)、concat(排序(r));
}
}

我认为这里的问题是分区步骤不一定会收缩输入数组。例如,让我们跟踪尝试排序[1,2]时发生的情况。在本例中,枢轴元素将是元素2。由于1>2为false,因此将1添加到列表
l
。由于2>2为false,因此将2添加到列表
l
。因此,对列表
l
的递归调用将具有与原始调用完全相同的参数,从而导致无限递归

若要解决此问题,请尝试将输入拆分为三个列表—一个较小的值、一个相等的值和一个较大的值。此代码如下所示:

function sort(data){
  if (data.length < 2){
    return data;
  } else {
    var l = [];
    var r = [];
    var e = [];
    var i = 0;
    var pivot = (data.length / 2) | 0;

    for(i = 0; i < data.length; i++) {
      if (data[i] > data[pivot]) {
        r.push(data[i]);
      } else if (data[i] < data[pivot]) {
        l.push(data[i]);
      } else {
        e.push(data[i]);
      }
    }  
    return sort(l).concat(e, sort(r)); 
  }
}
函数排序(数据){
如果(数据长度<2){
返回数据;
}否则{
var l=[];
var r=[];
var e=[];
var i=0;
var pivot=(data.length/2)| 0;
对于(i=0;i数据[pivot]){
r、 推送(数据[i]);
}else if(数据[i]
这个新版本将相等的元素显式地分组到它们自己的列表中,这样它们就不会按任何一个递归调用进行递归排序。它还优雅地处理重复的元素


希望这有帮助

JavaScript通过引用传递对象(数组也是对象)。如果要按值传递它们,则需要使用所述的拼接函数


请注意,这将创建大量数据副本。您可能希望使用本机sort()函数。

如果选择数组的最大值作为轴心元素,则
数据的所有值都将在数组
l
中结束,而
r
中没有值。因此,将使递归永不停止(并使
l
r
pivot
保持相同的值)。
除非这是一项脑力锻炼,否则使用
data.sort()
应该做得更好

每次递归调用都会覆盖l和r。您应该在排序函数之外初始化它们。@marteljn是的。但是如果我在返回之前放置console.log(l),它会打印相同的数组。所以我很困惑,我必须问:只调用
originalArray.sort()
,有什么不对?@marteljn-你确定吗?不是每个调用都有自己的堆栈帧和自己的
l
r
本地副本吗?我认为这不是问题所在。无限递归不是因为引用传递,而是因为原始代码没有正确处理需要处理的情况之一。您的问题没有提到任何关于无限递归的内容,而是关于变量没有改变…@Bergi-谢谢!我绝不是一个JS程序员,我不知道你能做到。让我们根据
sort
标记获取一些API访问调用的统计信息:)我敢打赌@templatetypedef今天因为stacksort实现获得了很多声誉:)投票率上升完全是因为这在有趣的stacksort项目()中起了作用,@templatetypedef想知道为什么答案现在这么受欢迎。。。感谢stacksort;)