【初级算法】排序算法-02

173 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

继续上一篇 排序算法-01

题目:定数组 [2, 1, 7, 9, 5, 8],要求按照从左到右、从小到大的顺序进行排序

归并排序

核心是分治。即将一个复杂的问题划分成两个或多个相同的子问题,然后子问题分成更小的问题,直到子问题可以简单的求解。最原本的问题就是子问题的合并。

解题思路

想将数组从中间划分 2组 进行排序,每组再对等分,一直递归地把子数组划分成更小的子数组,直到每个子数组里只有一个元素才开始排序

[2, 1, 7, 9, 5, 8] ^. [1,2,5,7,8,9]

[2,1,7] [9,5,8] |. [1,2,7] [5,8,9]

[2,1] [7] [9, 5] [8]. | [1,2] [7] [5,9] [8]

[1] [2] [7] [9] [5] [8]------>|

function sort(nums, left, right){
  if(left>=right) return;
  let mid=left +( right-left)/2;
  
  sort(nums, left, mid);
  sort(nums, mid+1, right);
  
  merge(nums, left ,mid,right);
}
​
function merge(nums, left, mid, right){
  let temps = nums.clone();
  let k = left, i = left, j = mid + 1;
  while(k<= right){
    if(i>mid) nums[k++] = temps[j++];
    else if(j>right) nums[k++] = temps[i++];
    else if(temps[j]<temps[i])nums[k++] = temps[j++];
    else nums[k++] = temps[i++];
  }
}

总结

比较时,出现四种情况

  • 左半边都处理完,右边未处理完,则只需将右边拷贝到左边
  • 右边处理完,左边未处理完,则只需将左边拷贝到右边
  • 左边数小于右边数,将左边数拷贝到合适位置,位移向前
  • 右边数小于左边数,则将右边数拷贝到合适位置,位移向前

快速排序

快速排序,其实也是分治的思想

将原数组随机划分成较小和较大的两个子数组,然后递归排序两个子数组

[2, 1, 7, 9, 5, 8] [2,1,7] [5,9,8]

[2,1,5] [7,9,8]

[1] [2, 5] [7] [9,8]

[1] [2] [5] [7] [8] [9]

function sort(nums,left ,right){
  if(left>=right) return;
  let p = quickSort(nums,left,right);
  
  sort(nums, left, p-1);
  sort(nums, p+1, right);
}
​
function quickSort(nums, left, right){
  swap(nums, range(left, right)m right);
  let i, j;
  for(i=left,j=left;j<right,j++){
    if(nums[j]<=nums[right]) {
      swap(nums, i++, j)
    }
  }
  swap(nums,i,j)
  return i
}
​

拓扑排序

上面几个算法都是数组方式去处理,但是拓扑排序中,主要研究的是顶点和顶点连线进行排序。拓扑排序一般用来解决具有依赖关系的任务。实现拓扑排序的前提条件:

  • 必须是有向图
  • 图中没有环