目录
大家好,我是Nick,今天我为小可爱们带来了期待已久的算法章目,有一定编程基础的家人们欢迎在评论区指点江山~ (萌新请绕道,建议收藏后期看哦~)
归并排序
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
需求:
排序前:{8,4,5,7,1,3,6,2}
排序后:{1,2,3,4,5,6,7,8}
排序原理:
- 尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。
- 将相邻的两个子组进行合并成一个有序的大组;
- 不断的重复步骤2,直到最终只有一个组为止。
代码展示:
Merge方法
public class Merge { /*比较v元素是否小于w元素*/ private static boolean less(Comparable v, Comparable w) { return v.compareTo(w) < 0; } //归并所需要的辅助数组 private static Comparable[] assist; /*对数组a中的元数进行排序*/ public static void sort(Comparable[] a) { //1.初始化辅助数组assist; assist = new Comparable[a.length]; //2.定义一个lo变量和hi变量,分别记录数组中最小的索引和最大的索引 int lo = 0; int hi = a.length - 1; //3.调用sort重载方法完成数组a中,从索引lo到索引hi的元素的排序 sort(a, lo, hi); } /*对数组a中从lo到hi的元素进行排序*/ private static void sort(Comparable[] a, int lo, int hi) { //做安全性校验 if (hi <= lo) { return; } //对lo到hi之间的数据进行分为两个数组 int mid = lo + (hi - lo) / 2; //分别对每一组数据进行排序 sort(a, lo, mid); sort(a, mid + 1, hi); //再把两个组中的数据进行归并 merge(a, lo, mid, hi); } /*对数组中,从lo到mid为一组,从mid+1到hi为一组,对这两组数据进行归并*/ private static void merge(Comparable[] a, int lo, int mid, int hi) { //定义三个指针 int i = lo; int p1 = lo; int p2 = mid + 1; //遍历,移动p1指针和p2指针,比较对应索引处的值,找出小的那个,放到辅助数组对应的索引处 while (p1 <= mid && p2 <= hi) { //比较对应索引处的值 if (less(a[p1], a[p2])) { assist[i++] = a[p1++]; } else { assist[i++] = a[p2++]; } } //遍历,如果p1指针没有走完,那么顺序移动p1指针,把对应的元素放到辅助数组索引处。 while (p1 <= mid) { assist[i++] = a[p1++]; } //遍历,如果p2指针没有走完,那么顺序移动p2指针,把对应的元素放到辅助数组索引处。 while (p2 <= hi) { assist[i++] = a[p2++]; } //把辅助数组中的元素拷贝到原数组中 for (int index = lo; index <= hi; index++) { a[index] = assist[index]; } } }
测试类
public class MergeTest { public static void main(String[] args) { Integer[] arr ={8,4,5,7,1,3,6,3}; Merge.sort(arr); System.out.println(Arrays.toString(arr)); } }
运行结果:
归并排序时间复杂度分析
归并排序是分治思想的最典型的例子,上面的算法中,对a[lo..hi]进行排序,先将它分为a[lo..mid]和a[mid+1..hi]两部分,分别通过递归调用将他们单独排序,最后将有序的子数组归并为最终的排序结果。该递归的出口在于如果一个数组不能再被分为两个子数组,那么就会执行merge进行归并,在归并的时候判断元素的大小进行排序。
归并排序的缺点
需要申请额外的数组空间,导致空间复杂度提升,是典型的以空间换时间的操作。
今天归并排序就告一段落啦~
我们下一篇,快速排序 再见!