排序算法

115 阅读1分钟

快速排序

💬 确定基准值,遍历数组,将大于基准值的值放到后面,小于基准值的值放在前面
🎉 针对内部

双边递归

const quick_sort = (nums) => {
    const sort1 = function(arr, left, right) {
        if (left > right) return
        let i = left, j = right
        const pivot = arr[i]
        while (i<j) {
            while (i<j && arr[j] >= pivot) {
                j--
            }
            arr[i] = arr[j]
            while (i<j && arr[i] <= pivot) {
                i++
            }
            arr[j] = arr[i]
        }
        arr[i] = pivot
        sort1(arr, left, i-1)
        sort1(arr, i+1, right)
    }
    sort1(nums, 0, nums.length-1)
    return nums
}

单边递归

STL优化点

  1. 单边递归法
  2. 无监督partition方法
  3. 三点取中法
  4. 小数据规模,停止快排过程
  5. 使用插入排序进行首尾

归并排序

💬 将两部分有序数组合并成一个
    分别将两个指针指向两个数组的第一个节点,比较两个数组,值较小的放入新空间中,指针向后移动一位
    排序后的数组放入原数组内
🎉 针对外部,进行分治

二路归并

const merge_sort = (nums, l, r) => {
  if (l>=r) return
  let mid = (l+r) >> 1, temp = []
  merge_sort(nums, l, mid)
  merge_sort(nums, mid+1, r)
  let k=0, p1 = l, p2 = mid + 1
  while (p1 <= mid || p2 <= r) {
    if ((p2 > r) || (p1 <= mid && nums[p1] <= nums[p2])) {
      temp[k++] = nums[p1++] 
    } else {
      temp[k++] = nums[p2++]
    }
  }
  for (let i=l; i<=r; i++) {
    nums[i] = temp[i-l]
  }
  return nums
}

多路归并

计数排序

💬 统计每一种数据的个数
🎉 简单的单值排序问题,排序问题中的数据值域很有限

基数排序

  1. 对个位的数据计数,求出前缀和,得到区域尾坐标
  2. 从后扫描数组,元素放入数组中,坐标对应前缀和中的值,归位,前缀和值减一
  3. 位数向前移动重复第一、第二步
const radix_sort = (nums) => {
  let cnt = new Array(65536).fill(0)
  let temp = new Array(nums.length)
  for(let i=0;i<nums.length;i++) cnt[nums[i] & 0xffff] += 1  // 统计低16位个数
  for (let i=1;i<65536;i++) cnt[i] += cnt[i-1]   // 前缀和
  for (let i=nums.length-1;i>=0;i--) temp[--cnt[nums[i] & 0xffff]] = nums[i]
  cnt = new Array(65536).fill(0) // 重置
  for(let i=0;i<temp.length;i++) cnt[(temp[i] & 0xffff0000) >> 16] += 1  // 统计高16位个数
  for (let i=1;i<65536;i++) cnt[i] += cnt[i-1]   // 前缀和
  for (let i=nums.length-1;i>=0;i--) nums[--cnt[(temp[i] & 0xffff0000) >> 16]] = temp[i]
}

拓扑排序

拓扑序不唯一

  1. 将入度为0的节点都放入队列中
  2. 依次出队列,将当前元素指向的节点入度减一
  3. 将入度变为0的节点放入队列中
  4. 直至队列为空
const topology_sort = (numCourses, prerequisites) => {
  let queue = [], deg = new Array(numCourses).fill(0), ans = []
  for (x of prerequisites) {
    if (!deg[x[0]]) deg[x[0]] = []
    deg[x[0]].push(x[1])
  }
  for (let i=0;i<deg.length;i++) {
    if (!deg[i]) {
      queue.push(i)
    }
  }
  while(queue.length) {
    let course = queue.shift()
    for (let i=0;i<deg.length;i++) {
      if (deg[i] && deg[i].includes(course)) {
        deg[i].splice(deg[i].indexOf(course), 1)
        if (!deg[i].length) queue.push(i)
      }
    }
  }
  if (ans.length - numCourses) ans = []
  return ans
}