一、引言
在JavaScript编程中,排序算法是非常常用的技术。掌握常见的排序算法有助于我们更好地处理和分析数据。本文将详细介绍JavaScript中常见的几种排序算法,包括冒泡排序、插入排序、选择排序、快速排序和归并排序。
二、冒泡排序
- 算法思想
冒泡排序是一种简单的排序算法,它通过重复地遍历列表,比较相邻的两个元素,如果前一个大于后一个,则交换它们的位置。遍历列表的次数等于列表的长度减一,因为每遍历一次,最大的元素就会移动到列表的末尾。
- 代码案例
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;
}
const list = [5, 3, 8, 4, 2];
console.log(bubbleSort(list));
三、插入排序
- 算法思想
插入排序是一种简单直观的排序算法。它从第一个元素开始,依次将后续的元素插入到已排序部分的适当位置,直到所有元素都排好序。插入排序的时间复杂度在最好的情况下为O(n),最坏的情况下为O(n^2)。
- 代码案例
function insertionSort(arr) {
for (let i = 1; i < arr.length; i++) {
let current = i;
while (current > 0 && arr[current] < arr[current - 1]) {
[arr[current], arr[current - 1]] = [arr[current - 1], arr[current]];
current--;
}
}
return arr;
}
const list = [5, 3, 8, 4, 2];
console.log(insertionSort(list));
四、选择排序
- 算法思想
选择排序是一种简单直观的排序算法。它在每一次遍历待排序序列时,选出最小(或最大)的一个元素,存放在序列的起始位置。然后,在剩余未排序序列中继续寻找最小(或最大)的元素,放到已排序序列的末尾。以此类推,直到全部待排序的数据排好序。
- 代码案例
function selectionSort(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 list = [5, 3, 8, 4, 2];
console.log(selectionSort(list));
五、快速排序
- 算法思想
快速排序是一种分治思想的排序算法。它通过选择一个基准元素,将数组分为两个子数组,一个包含比基准元素小的元素,另一个包含比基准元素大的元素。然后对这两个子数组分别进行递归排序。快速排序的平均时间复杂度为O(nlogn),但在最坏的情况下(如数组已排序或逆序),时间复杂度为O(n^2)。
- 代码案例
- 递归版本:
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
const pivotIndex = Math.floor(arr.length / 2);
const pivot = arr[pivotIndex];
const left = [];
const right = [];
for (let i = 0; i < arr.length; i++) {
if (i === pivotIndex) {
continue;
}
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}
const list = [5, 3, 8, 4, 2];
console.log(quickSort(list));
- 非递归版本:
function quickSort(arr, left = 0, right = arr.length - 1) {
if (left < right) {
const pivotIndex = partition(arr, left, right);
quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);
}
return arr;
}
function partition(arr, left, right) {
const pivot = arr[left];
let i = left;
let j = right;
while (i < j) {
while (i < j && arr[j] >= pivot) {
j--;
}
if (i < j) {
arr[i++] = arr[j];
}
while (i < j && arr[i] < pivot) {
i++;
}
if (i < j) {
arr[j--] = arr[i];
}
}
arr[i] = pivot;
return i;
}
const list = [5, 3, 8, 4, 2];
console.log(quickSort(list));
以上两个代码案例分别为快速排序的递归版本和非递归版本。非递归版本使用了迭代的方式,避免了递归带来的性能问题。两个版本都可以实现快速排序的功能,根据实际需求选择合适的版本即可。
六、归并排序
1.算法思想
归并排序(Merge Sort)是一种分治思想的排序算法。它的基本原理是将两个有序的数组合并成一个更大的有序数组。归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。
1.代码案例:
function merge(arr, left, mid, right) {
const n1 = mid - left + 1;
const n2 = right - mid;
let i = 0;
let j = 0;
let k = 0;
let L = [];
let R = [];
while i < n1 && j < n2 {
if (arr[left + i] < arr[mid + j]) {
L[k++] = arr[left + i];
i++;
} else {
R[k++] = arr[mid + j];
j++;
}
}
while i < n1 {
L[k++] = arr[left + i];
i++;
}
while j < n2 {
R[k++] = arr[mid + j];
j++;
}
return L.concat(R);
}
function mergeSort(arr) {
if (arr.length <= 1) {
return arr;
}
const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));
return merge(left, 0, mid - 1, mid);
}
const list = [5, 3, 8, 4, 2];
console.log(mergeSort(list));
以上代码实现了一个归并排序的函数。首先,我们定义了一个merge
函数,用于合并两个有序数组。然后,定义了一个mergeSort
函数,用于实现归并排序。在mergeSort
函数中,我们首先判断数组长度是否小于等于1,如果是,则直接返回数组。否则,我们计算数组的中间位置,递归地对左右两个子数组进行排序,然后调用merge
函数将两个有序数组合并成一个更大的有序数组。
通过以上代码,我们可以实现归并排序的功能,对给定的数组进行排序。