常见排序算法-图文版

avatar
前端工程师

一、选择排序

解法:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。

output.gif

function selectionSort(arr) {
  for(let i = 0; i < arr.length; i++) {
    let minIndex = i;
    for(let j = i + 1; j <arr.length; j++) {
      if(arr[minIndex] > arr[j]) minIndex = j
    }
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
    // let temp = arr[i]
    // arr[i] = arr[minIndex]
    // arr[minIndex] = temp
  }
  return arr;
}

二、冒泡排序

解法:通过连续地比较与交换相邻元素实现排序。

output.gif

function bubbleSort(arr) {
  for(let i = 0; i < arr.length; i++) {
    for(let j = i + 1; j < arr.length; j++) {
      if(arr[i]<arr[j]) {
        let temp = arr[i]
        arr[i] = arr[j]
        arr[j] = temp
      }
    }
  }
  return arr;
}

三、插入排序

解法:当前元素跟已排序的数组进行比较,如果该数字比已排序的数小,则将已排序数组中的元素后移,依次执行该步骤

output.gif

function insertSort(array) {
  for (let i = 1; i < array.length; i++) {
    let j = i - 1,
      base = array[i];
    for(j; j >= 0; j--) {
      if(array[j] > base){
         array[j+1] = array[j]
      }else break;
    }
    array[j+1] = base
  }
  console.log(array)
  return array;
}

四、快速排序

解法:选择数组中的某个元素作为“基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧

output.gif

function quickSort(arr) {
  if(arr.length <= 1) return arr; 
  let temp = arr[0],
    leftArr = [],
    rightArr = [];
  for(let i = 1; i < arr.length; i++) {
    if(arr[i]<temp) leftArr.push(arr[i])
    else rightArr.push(arr[i])
  }

  return [...quickSort(leftArr), temp, ...quickSort(rightArr)]
}

五、归并排序(向下分隔,向上合并)

解法:将数组从中间分隔,分为左右两个数组,然后递归这两个,直至数组长度等于1,开始向上合并。合并有序数组

output.gif

// 归并排序,将数组不断从中间分开,直至子数组长度为1时停止
function mergeSort(arr) {
  if (arr.length <= 1) {
    return arr; // 基本情况:如果数组只有一个元素或为空,则不需要排序
  }

  // 分成两个子数组
  const middle = Math.ceil(arr.length / 2);
  const left = arr.slice(0, middle);
  const right = arr.slice(middle);

  // 递归地对两个子数组进行分割
  const leftSorted = mergeSort(left);
  const rightSorted = mergeSort(right);

  console.log(`merge(${leftSorted},${rightSorted})`)
  // 合并子数组
  return merge(leftSorted, rightSorted);
}

//开始合并数组
function merge(left, right) {
  // console.log('merage', 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.concat(left.slice(leftIndex), right.slice(rightIndex));
}

var arr = [3,5,9,11,2,1,8,10]
console.log(mergeSort(arr))

算法比较

排序算法平均时间复杂度空间复杂度稳定性
选择排序O(n²)O(1)不稳定
冒泡排序O(n²)O(1)稳定
插入排序O(n²)O(1)稳定
快速排序O(nlogn)O(1)不稳定
归并排序O(nlogn)O(n)稳定
  • js中sort底层是用的什么排序算法?

当数组长度小于10时用插入排序,大于10的时候用快速排序.

参考链接