Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/393.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_Arrays_Sorting - Fatal编程技术网

Javascript 为什么排序时重复的元素出现在数组中?

Javascript 为什么排序时重复的元素出现在数组中?,javascript,arrays,sorting,Javascript,Arrays,Sorting,我知道如何使用Array.sort()在javascript中对数组进行排序,但我不知道在下面代码中的每次迭代中真正发生了什么。在这段代码中,在某些点,一些重复的元素开始出现在数组中。我在很多网站上搜索过这个谜团的解释,但我不明白为什么会发生这种情况。在chrome浏览器中运行此代码。我猜它是在浏览器的本地代码上运行的。但我想知道这背后的逻辑 我知道排序是基于正负值和零值的返回,但是为什么会出现重复的元素呢 var-arr=[4,3,2,1]; arr.sort(函数(a,b){ docume

我知道如何使用
Array.sort()
在javascript中对数组进行排序,但我不知道在下面代码中的每次迭代中真正发生了什么。在这段代码中,在某些点,一些重复的元素开始出现在数组中。我在很多网站上搜索过这个谜团的解释,但我不明白为什么会发生这种情况。在chrome浏览器中运行此代码。我猜它是在浏览器的本地代码上运行的。但我想知道这背后的逻辑

我知道排序是基于正负值和零值的返回,但是为什么会出现重复的元素呢

var-arr=[4,3,2,1];
arr.sort(函数(a,b){
document.getElementById(“output”).innerHTML+=(“[”+arr+“]”“++”a='+a+'b='+b+“
”); 返回a-b; }); document.getElementById(“输出”).innerHTML+=“[”+arr+“]”
因为默认JavaScript排序不是
O(n)

最有可能的排序方法是使用Heapsort或Mergesort(Firefox的SpiderMonkey引擎),这两种方法的最坏情况时间复杂度都是
O(n log n)
每个浏览器的引擎都使用这些排序算法中的一种

C++整数排序使用快速排序实现。它的最佳情况是
O(n log n)
,最坏情况是
O(n^2)

任何时间复杂度高于O(n)
的项目都将开始显示比项目总数更多的比较

注意:过去有报道称默认排序算法不稳定,建议您自己实现

编辑 这些值在数组中可能出现重复,因为您正在排序期间打印数组。如果您注意到
b
值是丢失的值,那么它将存储在临时交换变量中,同时与其他值进行比较

下面是一个快速排序实现的分步调试。您可以看到在关键步骤中发生了什么

String.repeat=函数(str,n){
返回Array.apply(null,数组(n)).map(String.prototype.valueOf,str).join(“”);
};
var调试器={};
Debugger.debugEnabled=true;
Debugger.indentChar=' ';
Debugger.println=函数(标签、缩进级别、rest){
if(Debugger.debugEnabled==true){
document.body.innerHTML+=[
重复(Debugger.indentChar,indentLevel)+
“”,标签“:”+
[].slice.call(参数,2).join(“”)+
“
” ].加入(“”); } }; var快速排序={}; QuickSort.sort=函数(项目){ println('Initial Array',0,items);//打印初始数组。 返回快速排序。\快速排序(items,0,items.length-1); }; 快速排序。\快速排序=功能(项目,左,右){ var指数; println('Before Sort',1,items);//在排序之前打印数组。 如果(items.length>1){ 索引=快速排序。\分区(项目,左,右); 如果(左<索引-1){ 快速排序。\快速排序(项目,左侧,索引-1); } 如果(索引<右){ 快速排序。\快速排序(项目、索引、右侧); } println('After Sort',1,items);//在排序后打印数组。 } 退货项目; }; 快速排序。_swap=函数(项目、第一个索引、第二个索引){ var temp=项目[firstIndex]; 项目[第一索引]=项目[第二索引]; println('交换期间',3,项);//交换期间打印数组。 项目[第二索引]=临时; }; 快速排序。_partition=函数(项目,左,右){ var pivot=项目[数学楼层((右+左)/2)],i=左,j=右; 而(我){ j--; }
如果(i简短的回答是:

对于在数组上运行的任何就地算法,都不能保证数组的中间值是有效的或完整的。Chrome选择实现其排序算法的方式,有一些中间步骤,其中数组的值是重复的,并且不是原始数组的完整集,但这是完全可以接受的由于排序算法尚未完成,因此无法执行

TLDR版本:

如果您想知道这背后的确切逻辑,可以查看Chrome在此使用的V8 javascript引擎的源代码

特别是在这种情况下

简而言之(长度=从;j--){ var tmp=a[j]; var order=comparefn(tmp,element);//这是调用比较函数的地方 如果(订单>0){ a[j+1]=tmp; }否则{ 打破 } } a[j+1]=元素; } };
通过此步骤进入第一个副本

第一次比较:比较前的数组[4,3,2,1]

i=1
j=0
tmp=a=4
element=b=3
order=1
arr[1]=tmp=a=4
arr[0]=element=b=3

第二次比较:比较前的数组[3,4,2,1]

i=2
j=1
tmp=a=4
element=b=2
order=2
arr[2]=tmp=a=4

第三次比较:比较前的数组[3,4,4,1]

i=2
j=0
tmp=a=3
element=b=2
(这仍然在外部for循环的内存中),
order=1
arr[1]=tmp=a=3
arr[0]=element=b=2

第四次比较:比较前的数组[2,3,4,1]


从这里,您可以看到为什么值会在数组中短暂地重复,因为for循环是如何在插入排序中设置的。它被设置为向数组写入最少的次数,并且搜索值保存在内存中,因此数组的中间值不必是有效的。

您看到这个答案了吗:我知道它有以下几点排序算法,但为什么会出现重复?在这个问题中,我
//This function was copied from the link above
function InsertionSort(a, from, to) {
  for (var i = from + 1; i < to; i++) {
    var element = a[i];
    for (var j = i - 1; j >= from; j--) {
      var tmp = a[j];
      var order = comparefn(tmp, element); //This is where your comparison function is called
      if (order > 0) {
        a[j + 1] = tmp;
      } else {
        break;
      }
    }
    a[j + 1] = element;
  }
};