[英]Is this implementation of bubble sort wrong?
Instead of using the usual do-while loops for sorting, if we use 2 for loops, would that be okay? 如果我们使用2 for循环,而不是使用通常的do-while循环进行排序,那会没关系吗?
let bubbleSort = (arr) => {
console.log(arr);
for(let i=0; i<arr.length; i++) {
for (j=0; j<arr.length; j++) {
if (arr[j] > arr[j+1]){
console.log("swapped (i,j)->", arr[j],arr[j+1])
let temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr
}
This returns the correct sorted array but is it any better than the do-while loop. 这会返回正确的排序数组,但它比do-while循环更好。 Both are O(n^2) time-complexity.
两者都是O(n ^ 2)时间复杂度。
All loop types do
, while
and for
are equivalent. 所有循环类型
do
, while
和for
是等价的。 They're just syntactic sugar for the programmer and ultimately boil down to the same thing at runtime. 它们只是程序员的语法糖,最终在运行时归结为同样的东西。
What you've posted here is a mostly correct implementation of bubble sort, but there are a few points of improvement available: 你在这里发布的是一个大致正确的冒泡排序实现,但有一些改进点:
Bug: the code is accessing an out of bounds index in the inner loop: iterate to j < arr.length - 1
instead of j < arr.length
because of the arr[j+1]
statement. 错误:代码正在访问内部循环中的越界索引:由于
arr[j+1]
语句,迭代到j < arr.length - 1
而不是j < arr.length
。 Most languages will crash or exhibit undefined behavior for an out of bounds array access, but JS just compares the value against undefined
and carries on. 对于越界数组访问,大多数语言都会崩溃或表现出未定义的行为,但JS只是将值与
undefined
进行比较并继续进行。
Potential bug: the inner loop creates a global j
variable in the inner loop (thanks to Kaiido for pointing this out). 潜在的错误:内部循环在内部循环中创建一个全局
j
变量(感谢Kaiido指出这一点)。 This variable's value will persist beyond this function and might cause unexpected behavior elsewhere in the program. 此变量的值将持续超出此函数,并可能导致程序中其他位置的意外行为。 Declare variables with
let
(or const
if the variable shouldn't be reassigned) to ensure that they are scoped locally to the block. 使用
let
声明变量(如果不应该重新赋值变量,则为const
)以确保它们在本地作用于块。
After the first iteration of the outer loop, the rightmost element in the array is in its final and sorted location (because it's the largest element in the array). 在外部循环的第一次迭代之后,数组中最右边的元素位于其最终和排序位置(因为它是数组中的最大元素)。 After the second iteration of the outer loop, the last two elements of the array are in their final sorted positions.
在外循环的第二次迭代之后,数组的最后两个元素处于它们的最终排序位置。 And so on.
等等。 Therefore, we can shorten the number of iterations of the inner loop as follows:
j < arr.length - 1 - i
. 因此,我们可以按如下方式缩短内循环的迭代次数:
j < arr.length - 1 - i
。
If on any iteration no swaps were performed, we can break--the array is already sorted. 如果在任何迭代中没有执行交换,我们可以破坏 - 数组已经排序。
These optimizations don't improve the time complexity, which is O(n 2 ) as you say, but they're worth thinking about, as similar optimization approaches can help speed up real-world sort routines. 这些优化并没有改善时间复杂度,正如你所说的那样是O(n 2 ),但它们值得思考,因为类似的优化方法可以帮助加速现实世界的排序例程。
A few style points to consider: 需要考虑几个风格点:
[]
s). []
s中)。 temp
variable when swapping values. temp
变量。 As pointed out in the comments, this has a performance penalty due to the overhead of array object creation per swap, so it should be compiled out in a production build (although bubble sort wouldn't be appropriate in production anyway). Here's a possible re-write: 这是一个可能的重写:
const bubbleSort = arr => { for (let i = 0; i < arr.length; i++) { let swapped = false; for (let j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j+1]) { [arr[j], arr[j+1]] = [arr[j+1], arr[j]]; swapped = true; } } if (!swapped) { break; } } return arr; }; for (let i = 0; i < 10000; i++) { const arr = Array(100).fill().map(e => ~~(Math.random() * 30)); const expected = JSON.stringify(arr.slice().sort((a, b) => a - b)); const actual = JSON.stringify(bubbleSort(arr.slice())); if (actual !== expected) { throw new Error(`test failed: expected ${expected} but got ${actual}`); } } console.log("10000 tests passed");
Fun follow-up exercises: 有趣的后续练习:
Array#sort
. Array#sort
。 This way, you can sort arrays of objects or specify the order of the sort. console.time
(thanks to Medet for the idea). console.time
对其他排序例程进行基准测试(感谢Medet的想法)。 How much do the optimizations help?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.