系列文章目录
【每天学一点 - 算法篇 - 排序 - 插入排序】
【每天学一点 - 算法篇 - 排序 - 希尔排序】
【每天学一点 - 算法篇 - 排序 - 堆排序】
前言
新年新春,祝大家虎年大吉大利,如虎添翼,虎年事事顺心如意
一、什么是归并排序
传统艺能之“望文生义”,归并排序其实是(拆分)归并排序,先把整个序列拆分,拆分,再拆分,拆分到最小,然后每个最小单位再分别归到一起,并在一块进行比较排序。
二、归并排序原理
1、思路
上面的解释其实已经大概能感觉出来,归并排序其实就是最经典的“分治算法”的排序。
所谓分治算法就是把一个复杂的问题分成一个一个简单的问题,然后再把所有的答案合并起来,就形成了最后的结果,是不是跟(拆分)归并排序很般配
2、示例
3、抽象
如果除非数组已经完全不可分解,否则数组分为左右两部分,两部分分别进行归并排序
左右两部分单独排序完成后,再把左右两部分合在一起进行排序,
排序方式为:
取左右最左一个(最小数字)比较,小的为最小数字
大的一个跟最小数字数组左边第二个(第二小数字)进行比较
比较数字依次向右变化,直到所有数字并入新的有序数组进行返回
三、归并排序代码
实现方法
public int[] mergeSort(int[] a) {
if (a.length == 1) {
return a;
}
int[] left = new int[a.length / 2];
System.arraycopy(a, 0, left, 0, a.length / 2);
left = mergeSort(left);
int[] right = new int[a.length - a.length / 2];
System.arraycopy(a, a.length / 2, right, 0, a.length - a.length / 2);
right = mergeSort(right);
for (int i = 0, j = 0, k = 0; k < a.length; k++) {
if (i < a.length / 2 && (j == a.length - a.length / 2 || left[i] < right[j])) {
a[k] = left[i];
i++;
} else {
a[k] = right[j];
j++;
}
}
return a;
}
测试方法
@Test
public void mergeSort() {
int[] a = new int[]{3, 9, 5, 4, 8, 7, 1, 6, 2};
System.out.println(Arrays.toString(new Sort().mergeSort(a)));
}
四、归并排序复杂度
老规矩,先写结论
O(NlogN)
其实看堆排序分析的时候就知道,
插入排序最大的问题就是完成一个数字位置定位时的所有比较关系并没有保存,
下一个数字再进行定位,还是几乎要和所有的数字再比较一遍,
而希尔排序或者堆排序就是利用数据结构储存了比较关系,
尽量让每次比较之后的所有数字趋向于自己正确的位置。
而归并排序就是更加简单粗暴的方式,
通过牺牲空间去换取时间,
增加更多的临时数组,来保存下每次的比较关系,
也就减少定位后面数字的正确位置的时间
总结
坚持,坚持,还是坚持,缺一天就想缺第二天,缺第二天就会觉得放弃了其实也无所谓,一定要督促自己坚持下去
说给三天写一更的可耻自己