一些常用的排序算法讲解 | 刷题打卡

90 阅读3分钟

前言

本文将介绍几种常见的排序算法,包括改进后的冒泡排序,插入排序,并归排序,选择排序

改进后的冒泡排序

思路

方法一:设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可

方法二:进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。

代码

// 改进后的冒泡排序
//方法一
function bubbleSort1(arr) {
    var i = arr.length - 1;
    while (i > 0) {
        var pos = 0;
        for (let j = 0; j < i - pos; j++) {
            if (arr[j] > arr[j + 1]) {
                pos = j;
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
            i = pos;
        }
    }
    return arr;
}

// 改进的冒泡排序
//方法二
function bubbleSort2(arr) {
    let low = 0;
    let high = arr.length - 1;
    while (low < high) {
        for (let i = 0; i < high; i++) {
            if (arr[i] > arr[i + 1]) {
                let temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
            }
        }
        high--;
        for (let j = high; j > low; j--) {
            if (arr[j] > arr[j + 1]) {
                let temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
        low++;
    }
    return arr;
}

插入排序

思路

<1>.从第一个元素开始,该元素可以认为已经被排序;

<2>.取出下一个元素,在已经排序的元素序列中从后向前扫描;

<3>.如果该元素(已排序)大于新元素,将该元素移到下一位置;

<4>.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

<5>.将新元素插入到该位置后;

<6>.重复步骤2~5。

代码

function binaryInsertSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        let left = 0;
        let right = i - 1;
        let key = arr[i];
        //使用二分法找到已排序的数组中大于key的项
        while (left <= right) {
            let middle = parseInt((left + right) / 2);
            if (key < arr[middle]) {
                right = middle - 1;
            } else {
                left = middle + 1; //最后在已排序的数组中大于key的value的索引是left。
            }
        }
        for (let j = i - 1; j >= left; j--) {
            arr[j + 1] = arr[j];
        }
        arr[left] = key
    }
    return arr;
}

选择排序

思路

每次循环选取一个最小的数字放到前面的有序序列中。

代码

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[minIndex],arr[i]] = [arr[i],arr[minIndex]]
    }
}

并归排序

思路

并归排序,时间复杂度:O(nlogn)

分割:

将数组从中点进行分割,分为左、右两个数组

递归分割左、右数组,直到数组长度小于2

归并:

如果需要合并,那么左右两数组已经有序了。

创建一个临时存储数组temp,比较两数组第一个元素,将较小的元素加入临时数组

若左右数组有一个为空,那么此时另一个数组一定大于temp中的所有元素,直接将其所有元素加入temp

代码

function mergeSort(array) {
    if (array.length < 2) {
      return array;
    }
    const mid = Math.floor(array.length / 2);
    const front = array.slice(0, mid);
    const end = array.slice(mid);
    return merge(mergeSort(front), mergeSort(end));
  }

  function merge(left, right) {
    const result = [];
    while(i < left.length && j < right.length) {
        if (left[i] <= right[j]) {
          result.push(left[i++])
        } else {
          result.push(right[j++])
        }
      }
      //遍历结束后,左右两个可能会有剩余,就把剩余的数组添加到result的后面。
      if (i < left.length) {
        result.push(...left.slice(i))
      } else {
        result.push(...right.slice(j))
      }
      return result
  }