方法一
相邻元素两两比较,当一个元素大于右侧相邻元素时,交换它们的位置,当一个元素小于或等于右侧相邻元素时,位置不变。
/**
*
* @param {待排序数组} arr
* 时间复杂度:O(n^2)
* 稳定排序(相邻元素相等时不交换位置)
* 空间复杂度:O(1) 直接修改原数组
*/
function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 利用数组解构赋值 交换j和j+1
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
}
方法二
这是对方法一的优化版,增加有序标记,如果某一轮比较,一个元素都没有交换就代表整个数组已经有序。
/**
*
* @param {待排序数组} arr
*/
function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
// 有序标记,每一轮的初始值都是true
let isSorted = true;
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 利用数组解构赋值 交换j和j+1
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
// 进这个if循环,就代表有元素进行交换,所以就不是有序的,把标记改为false
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
方法三
这是对方法一的进一步优化,优化每一轮比较的次数。增加一个border代表无序边界,然后把最后一次发生元素交换的位置点记下来,下一轮比较就只需要比到这儿为止。
/**
*
* @param {待排序数组} arr
*/
function bubbleSort(arr) {
// 记录最后一次交换的边界
let lastExchangeIndex = 0;
// 无序数组的边界,每次比较只需要比到这里为止
let sortBorder = arr.length - 1;
for (let i = 0; i < arr.length - 1; i++) {
// 有序标记,每一轮的初始值都是true
let isSorted = true;
for (let j = 0; j < sortBorder; j++) {
if (arr[j] > arr[j + 1]) {
// 利用数组解构赋值 交换j和j+1
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
// 进这个if循环,就代表有元素进行交换,所以就不是有序的,把标记改为false
isSorted = false;
// 更新为最后一次交换元素的位置
lastExchangeIndex = j;
}
}
sortBorder = lastExchangeIndex;
if (isSorted) {
break;
}
}
}
方法四:鸡尾酒排序
鸡尾酒排序算法相比冒泡排序差别点就在,鸡尾酒是双向排序。就像排钟从左摆到右后,立即从当前位置摆回去。
缺点:代码复杂
适用场景:大部分元素已经有序,摆几下就能完全有序
/**
*
* @param {待排序数组} arr
*/
function bubbleSort(arr) {
for (let i = 0; i < arr.length / 2; i++) {
// 有序标记,每一轮的初始值都是true
let isSorted = true;
for (let j = i; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 利用数组解构赋值 交换j和j+1
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
// 进这个if循环,就代表有元素进行交换,所以就不是有序的,把标记改为false
isSorted = false;
}
}
if (isSorted) {
break;
}
// 顺摆轮结束之前,把isSorted重新标记为true,下面就开始逆摆
isSorted = true;
for (let j = arr.length - i - 1; j > i; j--) {
if (arr[j] < arr[j - 1]) {
// 利用数组解构赋值 交换j和j+1
[arr[j], arr[j - 1]] = [arr[j - 1], arr[j]]
// 进这个if循环,就代表有元素进行交换,所以就不是有序的,把标记改为false
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}