关于数组的六种排序

在计算机科学中,排序是将一串数据按照一定的顺序排列起来的算法。排序算法是解决实际问题中常用的基本算法之一,应用范围非常广泛。

常见的排序算法有冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序等等。不同的排序算法有着不同的特点和应用场景,选择适合的排序算法可以提高程序的效率。

下面我们就来深入浅出的讲解一下几种排序算法的原理和应用,同时也提供相关的 TypeScript 代码实现。

冒泡排序

冒泡排序是一种简单直观的排序方法,它的基本思想是通过不断比较相邻的元素,重复地将大的元素交换到后面,从而逐步将整个序列排好顺序。

下面是 TypeScript 实现冒泡排序的代码:

  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    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;
}

选择排序

选择排序的基本思想是每次将未排序序列中最小的元素作为已排序序列的末尾元素。即每次选择一个最小的数放到前面已经排序好的序列的最后。

下面是 TypeScript 实现选择排序的代码:

  const len = arr.length;
  let minIndex: number;
  for (let i = 0; i < len - 1; i++) {
    minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
  }
  return arr;
}

插入排序

插入排序的基本思想是将未排序序列中的元素插入到已排序序列中的恰当位置,使得插入后的序列仍然有序。

下面是 TypeScript 实现插入排序的代码:

  const len = arr.length;
  let preIndex: number, current: number;
  for (let i = 1; i < len; i++) {
    preIndex = i - 1;
    current = arr[i];
    while (preIndex >= 0 && arr[preIndex] > current) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = current;
  }
  return arr;
}

归并排序

归并排序采用分治的思想,将原序列分成较小的序列,每个子序列排序后合并成一个大的有序序列。

下面是 TypeScript 实现归并排序的代码:

function mergeSort(arr: number[]): number[] {
  if (arr.length <= 1) {
    return arr;
  }
  const mid = Math.floor(arr.length / 2);
  const leftArr = arr.slice(0, mid);
  const rightArr = arr.slice(mid);
  return merge(mergeSort(leftArr), mergeSort(rightArr));
}

function merge(left: number[], right: number[]): number[] {
  const res: number[] = [];
  let leftIndex = 0;
  let rightIndex = 0;
  while (leftIndex < left.length && rightIndex < right.length) {
    if (left[leftIndex] < right[rightIndex]) {
      res.push(left[leftIndex]);
      leftIndex++;
    } else {
      res.push(right[rightIndex]);
      rightIndex++;
    }
  }
  return res.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}

快速排序

快速排序采用分治的思想,将原序列分成两个子序列,然后对子序列排序,最后将两个子序列合并成一个有序序列。

下面是 TypeScript 实现快速排序的代码:

function quickSort(arr: number[]): number[] {
  if (arr.length <= 1) {
    return arr;
  }
  const pivot = arr[0];
  const leftArr: number[] = [];
  const rightArr: number[] = [];
  for (let i = 1; i < arr.length; i++) {
    arr[i] < pivot ? leftArr.push(arr[i]) : rightArr.push(arr[i]);
  }
  return quickSort(leftArr).concat(pivot).concat(quickSort(rightArr));
}

堆排序

堆排序将待排序序列构建成一个大根堆或小根堆,然后将堆顶元素放到序列的最后,再将剩余元素重新构建成一个堆,重复上述操作直到整个序列有序。

下面是 TypeScript 实现堆排序的代码:

function heapSort(arr: number[]): number[] {
  buildHeap(arr);
  for (let i = arr.length - 1; i > 0; i--) {
    swap(arr, 0, i);
    maxHeapify(arr, 0, i - 1);
  }
  return arr;
}

function buildHeap(arr: number[]): void {
  const len = arr.length;
  const lastNode = len - 1;
  const parent = Math.floor((lastNode - 1) / 2);
  for (let i = parent; i >= 0; i--) {
    maxHeapify(arr, i, len - 1);
  }
}

function maxHeapify(arr: number[], start: number, end: number): void {
  let root = start;
  let child = root * 2 + 1;
  while (child <= end) {
    if (child + 1 <= end && arr[child] < arr[child + 1]) {
      child++;
    }
    if (arr[root] < arr[child]) {
      swap(arr, root, child);
      root = child;
      child = root * 2 + 1;
    } else {
      return;
    }
  }
}

function swap(arr: number[], i: number, j: number): void {
  [arr[i], arr[j]] = [arr[j], arr[i]];
}

以上就是六种常见的排序算法以及 TypeScript 实现代码。在实际开发中,我们需要根据不同的应用场景选择不同的排序算法,从而提高程序的效率。

你可能感兴趣的:(关于数组的六种排序)