介绍冒泡排序前先了解一下解构:
解构
JavaScript中的解构是一种语法,它可以让开发者从数组或对象中快速获取并声明其中的值,而不需要使用传统的索引或属性名称来获取。解构赋值可以使代码更加简洁易读,并且可以方便地从一个数据结构中提取出需要的数据。
在JavaScript中,数组和对象都支持解构操作。
- 数组解构
数组解构可以将一个数组中的元素对应到多个变量中,示例如下:
ini
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c); // 输出:1 2 3
上述代码中,我们使用方括号[]来声明一个数组,然后使用解构赋值将数组中的元素分别赋值给了变量a、b和c。
- 对象解构
对象解构可以将一个对象中的属性对应到多个变量中,示例如下:
ini
const obj = { name: 'Tom', age: 18 };
const { name, age } = obj;
console.log(name, age); // 输出:Tom 18
上述代码中,我们使用花括号{}来声明一个对象,然后使用解构赋值将对象中的属性分别赋值给了变量name和age。
- 除了直接使用属性名来解构对象外,还可以使用别名来重命名解构出来的变量,示例如下:
ini
const obj = { name: 'Tom', age: 18 };
const { name: n, age: a } = obj;
console.log(n, a); // 输出:Tom 18
上述代码中,我们使用别名n和a分别代替了属性名name和age来解构对象,并将它们赋值给了变量n和a。
需要注意的是,如果对象中不存在对应属性,那么解构出来的变量会被赋值为undefined。
- 直接解构所有元素
js
const agt = ['里皮','梅西','劳塔罗','圣马丁']
// 一次性的解构出来 解构
//按照顺序解
// const [captain,mx] = agt //加一个变量可以多解构一个
const [captain,...players] = agt //...player 会解构出剩下所有的元素
console.log(captain,...players); //打印所有的数组元素
冒泡排序
冒泡排序(Bubble Sort)是一种简单的排序算法,它通过重复比较相邻的元素并交换位置来实现排序。这个过程会不断地将最大(或最小)的元素"浮"到数组的末尾,因此得名冒泡排序。
下面是 JavaScript 中实现冒泡排序的一种常见方式:
JavaScript
//冒泡排序
function bubbleSort(arr){
let len = arr.length; //缓存数组长度
for(let i = 0; i < len; i++) {
//len - i - 1是因为9在第一轮已经排好了,第二轮排好了8
for(let j = 0; j < len - i - 1; j++) {
//本轮的最大值到最右边
if(arr[j] > arr[j+1]) { // 相邻元素交换位置
[arr[j], arr[j+1]] = [arr[j+1], arr[j]] //解构 赋值
}
}
}
return arr
}
在上面的代码中,bubbleSort
是一个接受数组作为参数的函数。它使用两个嵌套的循环来遍历数组,并比较相邻的元素进行交换。外层循环控制需要比较的轮数,内层循环则负责执行实际的比较和交换。
在每次内层循环的迭代中,如果当前元素大于相邻元素,则交换它们的位置。通过这样的比较和交换,最大的元素会"浮"到数组的末尾。
冒泡排序的时间复杂度为 O(n^2),其中 n 是数组的长度。尽管冒泡排序是一种简单直观的排序算法,但它在处理大量数据时效率较低,因此通常不适用于大规模的排序任务。
冒泡排序的特点:
- 两重for循环
- 每一轮会将当前这一轮最大的元素升到最右边
- 两两相邻的元素相互比较 [a,b] = [b,a]
- O(n^2)
- 稳定排序
- 效率低
冒泡可能会在排完后继续执行,所有我们得实现冒泡排序的优化
js
// 做标记,如果没有调换就提前退出
function bubbleSort(arr) {
console.time('改进冒泡排序');
const length = arr.length;
if (length <= 1) return;
// 也不需要执行那么多轮, 提前已排好了
for (let i = 0; i < length - 1; i++) {
let isSorted = true;
for (let j = 0; j < length - i -1; j++) {
if (arr[j] > arr[j+1]) {
[arr[j] , arr[j+1]] = [arr[j+1], arr[j]];
isSorted = false;
}
}
if (isSorted) {
break;
}
}
console.timeEnd('改进冒泡排序')
return arr
}
上方设定一个true值,如果不用交换顺序后,则返回。
js
// 数组的右边部分,有大部分排好序的,出现不需要比较j - i - 1的
// 标记上一轮,完成交换的最后一次的位置,最后的位置<j - i - 1
const bubbleSort = (arr)=>{
let tmp = 0
let lastExchangeIndex = 0
let arrLen = arr.length
let sortBorder = arr.length
for(let i =0;i < arrLen -1 ;i++){
let isSorted = true
for(let j =0;j<sortBorder;j++){
if(arr[j]>arr[j+1]){
[arr[j] , arr[j+1]] = [arr[j+1], arr[j]];
isSorted = false;
lastExchangeIndex = j;
}
}
sortBorder = lastExchangeIndex
if(isSorted){
break
}
}
return arr
}
该函数接收一个数组作为参数,返回排好序的数组。函数中定义了一些变量:
tmp
:一个临时变量,用于交换两个元素的值。lastExchangeIndex
:上次交换的位置,用于记录已经排好序的部分。arrLen
:数组长度,用于循环遍历数组。sortBorder
:排序边界,初始值是数组长度,每次内层循环结束后会将它更新为lastExchangeIndex
,即上次交换位置的下标,以此来缩小排序范围。isSorted
:是否已经排好序的标志,初始值为true
,如果有交换,则赋值为false
,如果内层循环结束后仍然为true
,则说明数组已经排好序,可以直接退出循环。
接下来,函数使用两个嵌套的for
循环来进行排序。外层循环控制排序轮数,内层循环控制每轮排序中的比较和交换操作。如果相邻两个元素的大小关系不符合排序要求,则交换它们的位置,将isSorted
标志赋值为false
,并更新lastExchangeIndex
的值。在内层循环结束后,将sortBorder
的值更新为lastExchangeIndex
,以缩小排序范围。如果isSorted
标志仍然为true
,则退出外层循环。
最后,函数返回排好序的数组。