算法学习:冒泡排序的一些思考
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。
网上抄的实现
function bubbleSort(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
console.log("STD当前/下一个:", arr[j], arr[j + 1]);
if (arr[j] > arr[j + 1]) {
// 相邻元素两两对比
var temp = arr[j + 1]; // 元素交换
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
console.log(bubbleSort([4, 2, 1, 3]));
特点
升序排序,每一轮的比较会把最大的数沉到最底。
降序排序,每一轮的比较会把最小的数沉到最底。
问题分解
- 相隔元素
- 两两比较,数组交换顺序
- 每进行一轮有一个排好
- 要进行几次比较
1. 怎么表示相邻元素
// 因为要取下一个元素,所以,在平时循环的基础上,再减1
var max = arr.lenght -1;
for (var i = 0; i < max; i++) {
var cur = arr[i];
var next = arr[i + 1];
}
// cur: 当前元素
// next: 下一个元素
2. 交换数组元素
function swap(arr, i, j) {
var temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
3. 一轮比较的逻辑
function bsort1(arr) {
for (var i = 0; i < arr.length - 1; i++) {
var cur = arr[i];
var next = arr[i + 1];
if (cur > next) {
swap(arr, i, i + 1);
}
}
return arr;
}
4. 要进行多少轮这种比较呢(结论: arr.length -1)
目前是简单的归纳,可能后面还要找更加可靠的证明来支持
//最多的情况,完全反序 [4,3,2,1]
//1: [3,2,1,4]
//2: [2,1,3,4]
//3: [1,2,3,4]
function bsort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
bsort1(arr);
}
return arr;
}
个人实现的完整代码如下
function swap(arr, i, j) {
var temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
function bsort1(arr, j) {
for (var i = 0; i < arr.length - 1 - j; i++) {
var cur = arr[i];
var next = arr[i + 1];
console.log("当前/下一个:", cur, next);
if (cur > next) {
swap(arr, i, i + 1);
}
}
return arr;
}
function bsort(arr) {
for (var i = 0; i < arr.length - 1; i++) {
bsort1(arr, i);
}
return arr;
}
var arr1 = [4, 3, 2, 1];
console.log(bsort(arr1));
结论:我的方法有问题,已经修复
1. 次数过多
(4,3/3/4类似这种已经循环过的,不需要再进行比较),貌似原版也是这种实现2. 里层循环应该受外层的影响
3. 改进版已经修改此问题
关于循环次数的问题,以 arr=[5,4,3,2,1]
为例
// 次数问题分析
function sub(arr, j) {
for (var i = 0; i < arr.length - 1 /* - j */; i++) {
var cur = arr[i];
var next = arr[i + 1];
console.log("当前/下一个:", cur, next);
}
return arr;
}
function main(arr) {
for (var i = 0; i < arr.length - 1; i++) {
sub(arr, i);
}
return arr;
}
var arr1 = [5, 4, 3, 2, 1];
main(arr1);
优化后的情况:
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 2 1
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 5 4
每循环一次,减少内层一次
1: 4(外层:i=0, 内层: 0,1,2,3)
2: 3(外层:i=1, 内层: 0,1,2)
3: 2(外层:i=2, 内层: 0,1)
4: 1(外层:i=3, 内层: 0)
优化前的情况:
5个元素:4*4=16次
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 2 1
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 2 1
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 2 1
当前/下一个: 5 4
当前/下一个: 4 3
当前/下一个: 3 2
当前/下一个: 2 1
循环次数(N为数组长度arr.length)
优化前: (N-1) * (N-1)
优化后:1 + 2 + 3 + …(N-1)