冒泡思想
打比方说想要一个数组从小到大排列
1.我们需要去两两比较两个数(i和i+1比较),如果我数值比你大我们位置调换(每循环一轮,都会有一位数到达正确的位置)
2.外循环一次,内循环一轮,那我们外循环该循环多少次呢?(我们先试一下以数组的长度为循环次数)
代码如下:
let arr = [3, 5, 2, 6, 4, 1]
for (let j = 0; j < arr.length; j++) {
console.log(`第${j}次冒泡`);
//每次都把全部值比较一遍处理:
for (let i = 0; i < arr.length; i++) {
console.log(arr[i], `-----`, arr[i + 1]);
//两两比较
if (arr[i] > arr[i + 1]) {
let temp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = temp
}
}
}
console.log(arr);
但是代码这样子的话,虽然基础的问题解决了,实现了冒泡排序,但是会有几个问题
问题1:内层比较时,数组最后一位也会去和i+1比较,那就会索引越界了
问题2:内层循环时,我们每比较一轮就会有一位数到达正确的位置,但每一轮比较都会把整个数组比较完(包括已经在正确索引上的值)
问题3:通过以上代码我们可以发现到倒数第二轮时,整个数组就已经排序好了,那么我们就只需要循环比数组的长度少一次的次数就可以了
优化冒泡排序
从以上代码我们可以发现一个规律,每一次内层循环,我们只需要循环上一次的次数-1(因为内层每执行一次就会有一个值到达正确的索引位置);且第一次内层循环的时候,只需要循环数组的长度-1次,就不会导致索引越界,那我们就可以解决问题1和问题2了,而我们外层循环的次数如果从1开始,那我们可以发现,外层循环的次数,刚好是内层循环需要减的数值,理论成立,我们来看看代码
代码如下:
//外层循环的次数是比长度少1
for (let j = 1; j < arr.length; j++) {
//内层循环的次数是依次递减,首次-1(避免最后一个越位)
for (let i = 0; i < arr.length - j; i++) {
if (arr[i] < arr[i + 1]) {
temp = arr[i]
arr[i] = arr[i + 1]
arr[i + 1] = temp
}
}
}
console.log(arr);