目录
前言
上一篇博客提到了归并两个有序数组,没用while语句写,这次归并排序使用while语句大大减少了代码量,这个模板也是前辈总结的模板,结构非常严谨。
逻辑分析
归并排序的思想就是整合一对对有序数组,如下图,每次我们都从中间去划分数组,第一次划分a数组,一分为二(a/2),再次划分,二分为四(a/4),第三次划分,四分为八(a/8),当数组仅有两个数的时候已经不能再分了,开始归并这两个有序数组。为什么说是归并有序数组呢?当一个数组只有两个数的时候,我们将它分为左右两边,这就相当于归并两个只存放了一个数的数组,这就是归并思想的巧妙之处,我们以有序的思想去对无序的数组进行排序。
复杂度分析
时间复杂度:
O(n)=n*logn(以2为底)
每次划分都除以2,所有我们得出一个公式:2^x = n,每次我们都要遍历一遍:n,则O(n)=x*n
空间复杂度:
O(n)=n
只需要开辟一个等长的数组
代码实现
package the_forth_week.homework;
//归并排序
public class mergeSort {
// 算法思想:先对数组进行递归排序,然后归并有序数组,需要用一个临时数组来存放归并后的数组
// 最后将临时数组替换原数组
public static void main(String[] args) {
int[] a = {1,5,3,2,9};
int[] temp = new int[5];
mergeSort(a, temp,0, a.length-1);
for (int num:a){
System.out.print(num + " ");
}
}
static void mergeSort(int[] a, int[] temp, int l, int r) {
// 先从递归排序数组
while (l >= r) return;
int mid = (l + r) / 2;
mergeSort(a, temp, l, mid);
mergeSort(a, temp,mid+1, r);
// 将一个数组分为左右两边
// 左边头指针i,右边头指针j,类似归并两个有序数组
int k = 0;
int i = l;
int j = mid + 1;
while (i <= mid && j <= r) {
if (a[i] <= a[j]){
temp[k++] = a[i++];
} else {
temp[k++] = a[j++];
}
}
while (i <= mid) {
temp[k++] = a[i++];
}
while (j <= r){
temp[k++] = a[j++];
}
// 把临时数组放入原数组,两个数组都要从起点开始
for (int m = l, n = 0; m <= r; m++, n++) {
a[m] = temp[n];
}
}
}