一、排序算法

一,排序算法

排序算法是《数据结构与算法》中最基本的算法之一。

排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。

排序算法平均时间复杂度空间复杂度排序方式稳定性
冒泡排序O(n²)O(1)In - place稳定
快速排序O(n log n)O(log n)In = place不稳定
插入排序O(n²)O(1)In = place稳定
归并排序O(n log n)O(n)Out = place稳定

1.冒泡排序(Bubble Sort)

冒泡排序(Bubble Sort)是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止,这意味着该数列已经排序完成。

function bubbleSort(arr) {
  let n = arr.length;
  for (let i = 0; i < n - 1; i++) { // 外层循环控制排序的轮数
    for (let j = 0; j < n - 1 - i; j++) { // 内层循环进行元素比较和交换
      if (arr[j] > arr[j + 1]) {
        // 交换元素
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
        //以上交换可以使用ES6(解构赋值)
        [arr[j], arr[j+1]] = [arr[j+1], arr[j]]
      }
    }
  }
  return arr;
}

// 示例数组
let arr = [64, 34, 25, 12, 22, 11, 90];
console.log("Sorted array: ", bubbleSort(arr));
  • 代码注解:
    1. 函数定义:bubbleSort(arr)接收一个数组arr为参数。
    2. 外层循环:循环的是排序的轮数
    3. 内层循环
      • 从第一个元素开始遍历数组,直到n - 1 - i (减 i 是为了每一轮的最后一个元素都是当前未排序部分最大的,不需要再比较)
      • 如果当前元素大于下一个元素,则交换这两个元素
    4. 交换元素:使用第三方变量交换值,或者ES6(解构赋值)
    5. 最后返回排序后的数组

2.快速排序(Quick Sort)

快速排序(Quick Sort)是一种高效的排序算法,采用分治策略来对一个数组进行排序。其基本思想是:

  1. 从数组中挑选一个元素,称为“基准”(pivot)。
  2. 重新排序数组,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数组的中间位置。
  3. 递归地(recursive)把小于基准值元素的子数组和大于基准值元素的子数组排序。
function quickSort(arr) {
  // 基准情况:如果数组长度小于或等于1,它已经是排序好的
  if (arr.length <= 1) {
    return arr;
  }

  // 选择一个基准点,这里选择数组的最后一个元素
  const pivot = arr[arr.length - 1];
  const left = []; // 定义左数组
  const right = []; // 定义右数组

  // 遍历数组,将元素分配到左右数组中
  for (let i = 0; i < arr.length - 1; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]); // 小于基准的放在左边
    } else {
      right.push(arr[i]); // 大于等于基准的放在右边
    }
  }

  // 递归排序左右数组,并将基准点放到中间
  //concat拼接数组元素
  return quickSort(left).concat([pivot],quickSort(right))
  //ES6的  ...(展开运算符/扩展运算符)
  //return [...quickSort(left), pivot, ...quickSort(right)];
}

// 示例数组
const arr = [7, 2, 1, 6, 8, 5, 3, 4];
console.log("Sorted array: ", quickSort(arr));
  • 代码注解:
    1. 基准选择:这里选择数组的最后一个元素作为基准点。
    2. 分区操作:遍历数组,将小于基准的元素放入 left 数组,将大于或等于基准的元素放入 right 数组。
    3. 递归调用:对 leftright 数组递归地进行快速排序。
    4. 合并结果:使用扩展运算符 ... 将排序好的 left 数组、基准点和 right 数组合并返回。

3.插入排序(Insertion Sort)

插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作方式是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上通常使用 in-place 排序(即只需用到 O(1) 的额外空间的排序)。

function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    let current = arr[i]; // 当前要插入的元素
    let j = i - 1;

    // 将当前元素与已排序的元素进行比较,如果已排序的元素大于当前元素,则将已排序元素向后移动
    while (j >= 0 && arr[j] > current) {
      arr[j + 1] = arr[j];
      j--;
    }

    // 插入当前元素到正确的位置
    arr[j + 1] = current;
  }
  return arr;
}

// 示例数组
const arr = [5, 2, 9, 1, 5, 6, 3];
console.log("Sorted array: ", insertionSort(arr));
  • 代码解释
    1. 外层循环:从数组的第二个元素开始,逐个遍历数组。
    2. 当前元素:将当前元素暂存到变量 current 中。
    3. 内层循环:使用一个while循环,将当前元素与它前面的元素进行比较。
      • 如果前面的元素大于当前元素,则将前面的元素向后移动一个位置。
      • 这个循环一直执行,直到找到第一个小于或等于当前元素的已排序元素,或者到达数组的开始。
    4. 插入元素:将当前元素插入到已排序序列的正确位置。

4.归并排序(Merge Sort)

归并排序(Merge Sort)是一种高效的排序算法,采用分治法(Divide and Conquer)的一个典型应用。它将数组分成两半,分别对这两半进行排序,然后将排序好的两半合并在一起。归并排序的性能非常稳定,时间复杂度总是 O(n log n)。

function mergeSort(arr) {
  if (arr.length <= 1) {
    return arr;
  }

  // 找到中间点,将数组分成两半
  const middle = Math.floor(arr.length / 2);
  const left = arr.slice(0, middle);
  const right = arr.slice(middle);

  // 递归地对左右两半进行排序
  const leftSorted = mergeSort(left);
  const rightSorted = mergeSort(right);

  // 合并两个已排序的数组
  return merge(leftSorted, rightSorted);
}

function merge(left, right) {
  let result = [];
  let leftIndex = 0;
  let rightIndex = 0;

  // 比较左右数组的元素,将较小的元素添加到结果数组中
  while (leftIndex < left.length && rightIndex < right.length) {
    if (left[leftIndex] < right[rightIndex]) {
      result.push(left[leftIndex]);
      leftIndex++;
    } else {
      result.push(right[rightIndex]);
      rightIndex++;
    }
  }

  // 当一边的元素已经完全加入结果数组后,将另一边的剩余元素加入
  return [
    ...result,
    ...left.slice(leftIndex),
    ...right.slice(rightIndex)
  ];
}

// 示例数组
const arr = [38, 27, 43, 3, 9, 82, 10];
console.log("Sorted array: ", mergeSort(arr));
  • 代码解释
    1. 基准情况:如果数组长度小于或等于1,直接返回数组,因为它已经是排序好的。
    2. 分割:找到数组的中间点,将数组分成两半。
    3. 递归排序:递归地对左右两半进行归并排序。
    4. 合并:使用 merge 函数合并两个已排序的数组。这个函数会遍历两个数组,比较并选择较小的元素添加到结果数组中,直到所有元素都被合并。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值