一、冒泡排序的原理
总结:从左到右,数组中相邻的两个元素进行比较,将较大的放到后面。
假设有10个数,第一轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动;接着第二个数和第三个数比较,如果第二个数大,第二个数和第三个数交换位置,否则不动……第九个数和第十个数比较,如果第九个数大,第九个数和第十个数交换位置,否则不动。第一轮循环结束,最大的数挪到了第十个数的位置,比较进行了9次。
第二轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动……第八个数和第九个数比较,如果第八个数大,第八个数和第九个数交换位置,否则不动。第二轮循环结束,第二大的数挪到了第九个数的位置,比较进行了8次。
……
第九轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动。第九轮循环结束,倒数第二大的数挪到了第二个数的位置,比较进行了1次。
总体原理:每轮比较找到最大的数。
示意图:
代码格式:
var arr = [1,20,4,60,10,35,65,18];
// 外层循环,控制比较轮数
for(var i = 0;i<arr.length-1;i++){
// 内层循环,控制每轮的比较次数
for(var j = 0;j<arr.length-1;j++){
// 比较相邻的俩个数
if(arr[j] > arr[j+1]){//升序排序
// 交换位置
let temp = 0;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
console.log(arr); // 1, 4, 10, 18,20, 35, 60, 65
二、选择排序的原理
总结:从第一个位置开始比较,找出最小的,和第一个位置互换,开始下一轮。(简单来说,就是拿一个值与其他的值进行比较。)
假设有10个数,第一轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动;接着第一个数和第三个数比较,如果第一个数大,第一个数和第三个数交换位置,否则不动……第一个数和第十个数比较,如果第一个数大,第一个数和第十个数交换位置,否则不动。第一轮循环结束,最小的数挪到了第一个数的位置,比较进行了9次。
第二轮循环,第二个数和第三个数比较,如果第二个数大,第而个数和第三个数交换位置,否则不动……第二个数和第十个数比较,如果第二个数大,第二个数和第十个数交换位置,否则不动。第二轮循环结束,第二小的数挪到了第二个数的位置,比较进行了8次。
……
第九轮循环,第九个数和第十个数比较,如果第九个数大,第九个数和第十个数交换位置,否则不动。第九轮循环结束,倒数第二小的数挪到了倒数第二个的位置,比较进行了1次。
示意图:
代码格式:
// 选择排序: 从第一个位置开始比较,找出最小的,和第一个位置互换,开始下一轮
var arr = [1, 20, 4, 60, 10, 35, 65, 18];
// 外层循环 控制比较轮数
for (var i = 0; i < arr.length - 1; i++) {
var main = i; //假设,main为最小值对应的索引值 // main = 1 20
// 内层循环,控制每轮的比较次数
// 每一轮开始先和那个元素开始比较:i+1
for (var j = i + 1; j < arr.length; j++) { // j = 20 4
if (arr[main] > arr[j]) { //如果 mian > j 即用第一个数来比较其他的数
main = j;
}
}
// 找出最小值,进行元素交换
// 如果最小值的索引值不是假设的索引,需要交换位置
if (main != i) {
let temp = 0;
temp = arr[i];
arr[i] = arr[main];
arr[main] = temp;
}
}
console.log(arr); //1, 4, 10, 18,20, 35, 60, 65
三、两者的区别
(1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;
(2)冒泡排序每一轮比较后,位置不对都需要换位置,而选择排序每一轮比较都只需要换一次位置;
(3)冒泡排序是通过数去找位置,而选择排序是给定位置去找数;
冒泡排序优缺点:
优点:比较简单,空间复杂度较低,是稳定的;
缺点:时间复杂度太高,效率慢;
选择排序优缺点:
优点:一轮比较只需要换一次位置;
缺点:效率慢,不稳定(举个例子5,8,5,2,9 我们知道第一遍选择第一个元素5会和2交换,那么原序列中2个5的相对位置前后顺序就破坏了)。