冒泡排序
通过相邻元素的比较和交换来将最大的元素逐步冒泡到数组末尾,重复这个过程直至排序完成。
- 两层循环,外层循环轮数是数组长度-1,内层循环每轮比较次数是数组长度-1-外层,比较前数和后数,最大的数被交换到数组末尾。
- 平均情况时间复杂度:O(n^2)
function bubbleSort(arr) {
// 外层循环控制比较轮数
for (let i = 0; i < arr.length - 1; i++) {
// 内层循环控制每轮比较次数
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]) {
// 交换相邻两个元素的位置
[arr[j], arr[j+1]] = [arr[j+1], arr[j]];
}
}
}
return arr;
}
// 示例
let arr = [3, 5, 1, 4, 2];
console.log(bubbleSort(arr)); // [1, 2, 3, 4, 5]
插入排序
将数组分为有序区和无序区,每次从无序区取出一个元素,插入到有序区中的正确位置,直到无序区为空为止。
- 外层循环控制无序区,从第二个元素开始(下标为1)。
- 内层循环控制有序区,找到无序区第一个元素应该插入的位置。由于有序区是已经排好序的,因此可以使用while循环从后往前遍历,找到第一个比temp小的元素的位置。
- 将有序区中大于temp的元素往后移动一位,为temp腾出位置。
- 将temp插入到正确位置。
- 平均情况时间复杂度:O(n^2)
function insertSort(arr){
//外层循环控制无序区,从第二个元素开始
for(let i=1; i<arr.length; i++){
//取出无序区的第一个元素
let temp = arr[i];
// j 为有序区的最后一个元素
let j = i - 1;
//内层循环找到temp应该插入的位置,操作 j
//内层循环没有长度,所以只能用 while循环
while(j>=0 && arr[j]>temp){
//将有序区大于temp的元素往后移一位
arr[j+1] = arr[j];
j--;
}
//将无序区的第一个元素 变成 有序区被后移的元素
arr[j+1] = temp
}
return arr;
}
const arr = [3,5,1,4,2];
console.log(insertSort(arr)); //[1,2,3,4,5]
选择排序
将数组分为已排序部分和未排序部分,每次从未排序部分选择最大的元素,放到已排序数组部分的末尾,重复这个过程直至排序完成。
- 数组分为已排序部分(第一个元素)和未排序部分。外层循环从数组的第一个元素开始,依次遍历未排序部分。
- 在内层循环中,我们通过找到未排序部分的最小值来更新最小值的索引。
- 如果找到比当前最小值更小的元素,我们就更新最小值的索引。
- 然后,我们将最小值与当前位置进行交换,将最小值放到已排序部分的末尾。
- 平均情况时间复杂度:O(n^2)
function selectSort(arr){
//外层循环遍历整个数组
for(let i=0; i<arr.length-1; i++){
let minIndex = i; //假设当前索引处的元素是最小值
//内层循环找到未排序部分的最小值
for(let j=i+1; j<arr.length; j++){
if(arr[j]<arr[minIndex]){
minIndex = j; //更新最小值的索引
}
}
//将最小值与当前位置交换
[arr[i], arr[minIndex]] = [arr[minIndex],arr[i]]
}
return arr;
}
const arr = [3,5,1,4,2];
console.log(selectSort(arr)); //[1,2,3,4,5]
其余三种排序方法见下一章