一起养成写作习惯!这是我参与「掘金日新计划 · 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
}
拓扑排序
上面几个算法都是数组方式去处理,但是拓扑排序中,主要研究的是顶点和顶点连线进行排序。拓扑排序一般用来解决具有依赖关系的任务。实现拓扑排序的前提条件:
- 必须是有向图
- 图中没有环