在 TypeScript 中高效排序:八大排序算法逐一击破
2023-10-23 20:50:25
TypeScript 中的八大排序算法
在计算机科学领域,排序算法是必不可少的工具。它可以将数据按特定顺序排列,从而使数据更易于理解、分析和操作。排序算法有很多种,每种算法都有其独特的特点和应用场景。在本文中,我们将探讨八大经典排序算法,并使用 TypeScript 语言实现它们。
1. 插入排序
插入排序是一种简单易懂的排序算法,它的基本思想是将一个元素插入到已经排序好的序列中,使其保持有序。插入排序的平均时间复杂度为 O(n^2),最坏时间复杂度也为 O(n^2),空间复杂度为 O(1)。
function insertionSort(arr: number[]): number[] {
for (let i = 1; i < arr.length; i++) {
const key = arr[i];
let j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
return arr;
}
2. 希尔排序
希尔排序是一种改进的插入排序,它通过将数组划分为多个子序列,然后对每个子序列进行插入排序来提高排序效率。希尔排序的平均时间复杂度为 O(n^(3/2)),最坏时间复杂度为 O(n^2),空间复杂度为 O(1)。
function shellSort(arr: number[]): number[] {
let gap = Math.floor(arr.length / 2);
while (gap > 0) {
for (let i = gap; i < arr.length; i++) {
const key = arr[i];
let j = i - gap;
while (j >= 0 && arr[j] > key) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = key;
}
gap = Math.floor(gap / 2);
}
return arr;
}
3. 选择排序
选择排序是一种简单的排序算法,它的基本思想是每次从数组中选择最小的元素,并将其放在数组的开头。选择排序的平均时间复杂度和最坏时间复杂度都为 O(n^2),空间复杂度为 O(1)。
function selectionSort(arr: number[]): number[] {
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;
}
}
const temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
4. 堆排序
堆排序是一种基于二叉堆的数据结构的排序算法。它先将数组构建成一个二叉堆,然后依次弹出堆顶元素,并将其插入到数组的末尾。堆排序的平均时间复杂度为 O(n log n),最坏时间复杂度也为 O(n log n),空间复杂度为 O(1)。
function heapSort(arr: number[]): number[] {
function buildMaxHeap(arr: number[]): void {
for (let i = Math.floor(arr.length / 2) - 1; i >= 0; i--) {
heapify(arr, i);
}
}
function heapify(arr: number[], i: number): void {
const left = 2 * i + 1;
const right = 2 * i + 2;
let largest = i;
if (left < arr.length && arr[left] > arr[largest]) {
largest = left;
}
if (right < arr.length && arr[right] > arr[largest]) {
largest = right;
}
if (largest !== i) {
const temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
heapify(arr, largest);
}
}
buildMaxHeap(arr);
for (let i = arr.length - 1; i > 0; i--) {
const temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
heapify(arr, 0);
}
return arr;
}
5. 冒泡排序
冒泡排序是一种简单易懂的排序算法,它的基本思想是将相邻的两个元素进行比较,如果前一个元素大于后一个元素,则交换这两个元素。冒泡排序的平均时间复杂度和最坏时间复杂度都为 O(n^2),空间复杂度为 O(1)。
function bubbleSort(arr: number[]): number[] {
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]) {
const temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
6. 快速排序
快速排序是一种高效的排序算法,它的基本思想是将数组划分为两个子数组,然后递归地对这两个子数组进行排序。快速排序的平均时间复杂度为 O(n log n),最坏时间复杂度为 O(n^2),空间复杂度为 O(log n)。
function quickSort(arr: number[], left: number, right: number): number[] {
if (left >= right) {
return arr;
}
const pivot = arr[Math.floor((left + right) / 2)];
let i = left;
let j = right;
while (i <= j) {
while (arr[i] < pivot) {
i++;
}
while (arr[j] > pivot) {
j--;
}
if (i <= j) {
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
quickSort(arr, left, j);
quickSort(arr, i, right);
return arr;
}
7. 归并排序
归并排序是一种稳定高效的排序算法,它的基本思想是将数组划分为两个子数组,然后对这两个子数组进行排序,最后合并这两个有序的子数组。归并排序的平均时间复杂度和最坏时间复杂度都为 O(n log n),空间复杂度为 O(n)。
function mergeSort(arr: number[]): number[] {
if (arr.length <= 1) {
return arr;
}
const mid = Math.floor(arr.length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}
function merge(left: number[], right: number[]): number[] {
const result: number[] = [];
let i = 0;
let j = 0;
while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
result.push(left[i]);
i++;
} else {
result.push(right[j]);
j++;