GO语言排序 | 青训营笔记

47 阅读3分钟

排序

最快的排序算法

python :-timsort

c++ -introsort

rust -pdqsort

经典排序算法

算法最优情况复杂度平均复杂度最差复杂度
插入排序O(n)O(n²)O(n²)
快速排序O(nlogn)O(nlogn)O(n²)
堆排序O(nlogn)O(nlogn)O(nlogn)
  • 插入排序在短序列速度最快
  • 快速排序在其他情况速度最快
  • 堆排序和长度关系不大

快速排序

  1. 选择数组中间数作为基数,并从数组中取出此基数
  2. 准备两个数组容器,遍历数组,逐个与基数比对,较小的放左边容器,较大的放右边容器;
  3. 递归处理两个容器的元素,并将处理后的数据与基数按大小合并成一个数组,返回。
let quickSort = function (arr) {
   // 递归出口就是数组长度为1
    if (arr.length <= 1) return arr
    //获取中间值的索引,使用Math.floor向下取整;
    let index = Math.floor(arr.length / 2)
    // 使用splice截取中间值,第一个参数为截取的索引,第二个参数为截取的长度;
    // 如果此处使用pivot=arr[index]; 那么将会出现无限递归的错误;
    // splice影响原数组
    let pivot = arr.splice(index, 1)[0],
        left = [],
        right = [];
    console.log(pivot)
    console.log(arr)
    for (let i = 0; i < arr.length; i++) {
        if (pivot > arr[i]) {
            left.push(arr[i])
        } else {
            right.push(arr[i])
        }
    }
    return quickSort(left).concat([pivot], quickSort(right));
}

归并排序

「时间复杂度: O(nlog(n))」

思路

  1. 将一个数组拆成A、B两个小组,两个小组继续拆,直到每个小组只有一个元素为止。
  2. 按照拆分过程逐步合并小组,由于各小组初始只有一个元素,可以看做小组内部是有序的,合并小组可以被看做是合并两个有序数组的过程。
  3. 对左右两个小数列重复第二步,直至各区间只有1个数。
const merge = (left, right) => { // 合并数组

    let result = []
    // 使用shift()方法偷个懒,删除第一个元素,并且返回该值
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift())
        } else {
            result.push(right.shift())
        }
    }
    while (left.length) {
        result.push(left.shift())
    }

    while (right.length) {
        result.push(right.shift())
    }
    return result
}

let mergeSort = function (arr) {
    if (arr.length <= 1)
        return arr
    let mid = Math.floor(arr.length / 2)
    // 拆分数组
    let left = arr.slice(0, mid),
        right = arr.slice(mid);
    let mergeLeftArray = mergeSort(left),
        mergeRightArray = mergeSort(right)
    return merge(mergeLeftArray, mergeRightArray)
}

let arr = [2, 9, 6, 7, 4, 3, 1, 7, 0, -1, -2]
console.log(mergeSort(arr))

插入排序

顾名思义:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

「时间复杂度: O(n*n)」

思路

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 重复步骤2~5。

选择排序

思路:每一次从待排序的数组元素中选择最大(最小)的一个元素作为首元素,直到排完为止

「时间复杂度O(n*n)」

思路

  1. 有n个数,需要排序n-1次
  2. 第一次选择最小值,放在第一位
  3. 第二次选择最小值,放在第二位
  4. …..重复该过程
  5. 第n-1次选择最小值,放在第n-1位

pdqsort

在不同条件下都拥有不错的性能。

对于短序列(长度为12——32)我们使用插入排序,其他情况使用快速排序,如果快速排序表现不佳,那么使用堆排序。