如下是一个基本的冒泡排序算法执行过程
- 外部循环
len
次 - 内部循环每次用
arr[i]
的值与arr[j]
的值进行比较 - 由于外部循环的
i
变量每次进入内部循环都不会改变,也就是arr[i]
的值进入内部循环后,都会以自身与arr[j]
(也就是整个数组的所有元素)比较一轮,结果是小于arr[i]
的数值都会被放到数组的开头 - 经过外层循环的一次次的进入内层循环的比对后,数组也依照从小到大的顺序排列了
let arr = [1, 3, 2]
const len = arr.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len; j++) {
const prevNum = arr[i]
const nextNum = arr[j]
// 如果成立,交换值的位置
if (prevNum > nextNum) {
arr[i] = nextNum
arr[j] = prevNum
}
}
}
步骤分解
第一轮外部循环 i = 0
i = 0;
j = 0;
arr = [1, 3, 2];
arr[i]也就是prevNum的值为1
arr[j]也就是nextNum的值为1
prevNum > nextNum不成立
交换条件不满足
arr保持现状[1, 3, 2]
i = 0;
j = 1;
arr = [1, 3, 2];
arr[i]也就是prevNum的值为1
arr[j]也就是nextNum的值为3
prevNum > nextNum不成立
交换条件不满足
arr保持现状[1, 3, 2]
i = 0;
j = 2;
arr = [1, 3, 2];
arr[i]也就是prevNum的值为1
arr[j]也就是nextNum的值为2
prevNum > nextNum不成立
交换条件不满足
arr保持现状[1, 3, 2]
i = 0;
j = 3;
arr = [1, 3, 2];
j < len不成立
循环结束
第二轮外部循环 i = 1
i = 1;
j = 0;
arr = [1, 3, 2];
arr[i]也就是prevNum的值为3
arr[j]也就是nextNum的值为1
prevNum > nextNum成立
交换位置条件满足
arr更新为[3, 1, 2]
i = 1;
j = 1;
arr = [3, 1, 2];
arr[i]也就是prevNum的值为1
arr[j]也就是nextNum的值为1
prevNum > nextNum不成立
交换条件不满足
arr保持原样[3, 1, 2]
i = 1;
j = 2;
arr = [3, 1, 2];
arr[i]也就是prevNum的值为1
arr[j]也就是nextNum的值为2
prevNum > nextNum不成立
交换条件不满足
arr保持原样[3, 1, 2]
i = 1;
j = 3;
arr = [3, 1, 2];
j < len不成立
循环结束
第三轮外部循环 i = 2
i = 2;
j = 0;
arr = [3, 1, 2];
arr[i]也就是prevNum的值为2
arr[j]也就是nextNum的值为3
prevNum > nextNum不成立
交换条件不满足
arr保持原样[3, 1, 2]
i = 2;
j = 1;
arr = [3, 1, 2];
arr[i]也就是prevNum的值为2
arr[j]也就是nextNum的值为1
prevNum > nextNum成立
交换条件满足
arr更新为[3, 2, 1]
i = 2;
j = 2;
arr = [3, 2, 1];
arr[i]也就是prevNum的值为2
arr[j]也就是nextNum的值为2
prevNum > nextNum不成立
交换条件不满足
arr保持原样[3, 2, 1]
i = 2;
j = 3;
arr = [3, 2, 1];
j < len不成立
循环结束
第四轮外层循环 i = 3
i < len不成立
循环结束
现在数组最终为[3, 2, 1]
。
优化1
分析
每次内部循环都会从let j = 0
开始,但其实这一步是没必要的,因为按照我们的算法,第一次进入内部循环时,i
和j
都是0
,arr[i]
和arr[j]
取的都是同一个值,而当非第一次的时候,索引为0
的取值就是上次最大的值。两种都不会发生位置交换。所以可以忽略。
如何忽略呢?
答案就是i
,i
的值其实隐含了已经遍历对比过的索引位置,我们只需要让内部循环从i
的索引开始。
for (let i = 0; i < len; i++) {
for (let j = i; j < len; j++) {
}
}
验证
用一个大数组,记录下循环次数
下面看下优化过的
效果显著。
优化2
分析
由于外部循环的i
和内部循环的j
初始化会相等,所以arr[i]
和arr[j]
会取到同一个位置的值比较一次,相同的值对比是不会发生位置交换的,也就没有必要对比,既然我们知道了,那么怎么优化这个操作呢?
答案就是让内部j
从第二位开始,避免和i
取同一个值的情况。
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
}
}
验证
聊胜于无。哈哈。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。