冒泡排序是我接触的第一种算法,最开始只是明白个大概,直到本身手写的时候才明白里面的思想,写下这篇文章,也是方便本身往后回顾。算法
用百度的话说:数组
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。 它重复地走访过要排序的元素列,依次比较两个相邻的元素,若是顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工做是重复地进行直到没有相邻元素须要交换,也就是说该元素列已经排序完成。 这个算法的名字由来是由于越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端同样,故名“冒泡排序”。markdown
用本身的话说:svn
冒泡排序是一种比较简单的排序算法,对数组进行升序排序时,会比较相邻元素,若是第一个元素大于第二个元素,就交换位置,不然就比较下两个元素。oop
[4,2,3,1]
使用冒泡排序,第一遍比较4和2,4>2,交换位置,获得
[2,4,3,1]
重复上一步,比较4和3,4>3,交换位置,获得
[2,3,4,1]
比较4和1,4>1,交换位置,获得
[2,3,1,4]
此时找到了数组中最大的元素4,以后重复上面的步骤去比较2和3...这里就很少作赘述。
在第一趟排序过程当中,4索引的变化:
index:3
↑
index:2
↑
index:1
↑
index:0
像是一个气泡不断上升且变大,故名冒泡排序
复制代码
最简版性能
function bubble(arr) {
let len = arr.length
for(let i = 0 ; i < len; i ++) {
// 当arr[j]为最后一个元素时,arr[j+1]不存在,没法比较,因此这里是j < len - 1
for(let j = 0; j < len - 1; j ++) {
console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j+1]}`)
if(arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
console.log(`=============================第${i+1}趟排序,结果为${arr}`)
}
return arr
}
console.log(bubble([4,2,3,1]))
// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// 第一个元素:3 第二个元素:4
// =============================第2趟排序,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:4
// =============================第3趟排序,结果为1,2,3,4
// 第一个元素:1 第二个元素:2
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:4
// =============================第4趟排序,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码
从输出结果来看,每趟遍历都要比较3次,但根据上面的冒泡原理可知,每遍历一次数组,就会找出最大/第二大/第三大...的数,因此上面的输出结果中,第2趟排序的3和4无需比较,由于第1趟排序已经能够确认4是最大的元素了。根据这个思路,优化方案flex
优化版v1优化
function bubble(arr) {
let len = arr.length
for(let i = 0 ; i < len; i ++) {
// 注意这里,由于每遍历一次数组就能够找到最大的项,也就是说每遍历一次须要比较的元素就少一个
for(let j = 0; j < len - 1 - i; j ++) {
console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j+1]}`)
if(arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
console.log(`=============================第${i + 1}趟排序结束,结果为${arr}`)
}
return arr
}
console.log(bubble([4,2,3,1]))
// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序结束,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// =============================第2趟排序结束,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// =============================第3趟排序结束,结果为1,2,3,4
// =============================第4趟排序结束,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码
从上面代码能够看出,比较次数从原来的4趟12次变成了4趟6次,但仍是能发现,当第三躺排序结束的时候,其实已经完成排序了,但仍是进行了第4趟排序。咱们想要的是若是后面的元素都不须要比较(已是排序好的),则直接结束排序,根据这个思路,优化方案ui
优化版v2url
function bubble(arr) {
let len = arr.length
for (let i = 0; i < len; i++) {
// 定义一个flag,表明后续元素是否须要交换位置
let flag = true
for (let j = 0; j < len - 1 - i; j++) {
console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j + 1]}`)
if (arr[j] > arr[j + 1]) {
// 须要交换位置,flag改成false
flag = false;
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
// 若是`某次循环`中不须要交换位置,那么意味着排序已经完成,无需继续遍历
if (flag) break;
console.log(`=============================第${i + 1}趟排序结束,结果为${arr}`)
}
return arr
}
console.log(bubble([4, 2, 3, 1]))
// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序结束,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// =============================第2趟排序结束,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// =============================第3趟排序结束,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码
冒泡排序的性能并不高,正常工做中也不经常使用,可是做为一种简单的排序方式,新手也能很容易理解。