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