算法(第四版)之归并排序

归并是指将两个较小的有序数组合并为一个大的有序数组, 利用这个方法的排序就叫做归并排序.

归并排序体现了分而治之的思想, 也就是将大问题分解为小问题, 解决完小问题就解决了大问题: 我们将无序数组分为两个小数组, 两个小数组在继续细分, 这样分到每一个小数组都只有一个元素, 那么自然这个小数组就是有序的了, 在一一合并, 这样就组成了一个大数组

 

 总体来说还是很好理解的, 首先我们先写合并部分的代码:

 1 public static void merge(int[] a, int lo, int mid, int hi) { //归并操作
 2         int i = lo, j = mid + 1;
 3         for(int k = lo; k <= hi; k++) {
 4             aux[k] = a[k];
 5         }
 6         for(int k = lo; k <= hi; k++) {
 7             if(i > mid) // 左边元素取尽
 8                 a[k] = aux[j++];
 9             else if(j > hi) // 右边元素取尽 
10                 a[k] = aux[i++];
11             else if(aux[j] > aux[i])
12                 a[k] = aux[i++];
13             else 
14                 a[k] = aux[j++];
15         }
16     }

merge()函数的意思是将lo到hi这一段的数组用mid分为两部分, 然后用每次讲这两个小数组的最前面的数中最小的那个加到大数组中, 当两个数组都取尽时, 合并完成, 同时保证了大数组的有序性

我们发现, 合并过程有一个不好的地方, 就是需要临时定义一个数组临时存储数据, 由于这个merge()函数会调用很多次, 所以我们就定义在了函数的外面, 避免多次定义数组影响性能.

接下来我们些排序的主体, 我们可以想到有递归和递推两种方式, 在书上把这两个称为自顶向下的归并排序和自底向上的归并排序, 我们先写递归的归并(自顶向下):

1 public static void top_down_sort(int[] a, int lo, int hi) { //自顶向下的归并(递归)
2         if(hi <= lo)
3             return;
4         int mid = lo + (hi-lo)/2;
5         top_down_sort(a ,lo, mid);
6         top_down_sort(a, mid+1, hi);
7         merge(a, lo, mid, hi);
8     } 

可以很清楚的理解代码吧数组分成两部分, 并递归这两个部分, hi<=lo时, 小数组中只有一个元素, 递归停止

接下来, 是自底向上(递推)的代码:

1 public static void down_top_sort(int[] a) { //自底向上的归并(递推)
2         int N = a.length;
3         for(int sz = 1; sz < N; sz++) //sz为子数组大小
4             for(int lo = 0; lo < N-sz; lo += sz*2) // lo为子数组索引
5                 merge(a, lo, lo+sz-1, Math.min(lo+sz*2-1, N-1));
6     }

这个就是直接从大小为1的小数组开始, 然后两两合并, 直到组成大数组

归并排序的速度很快,它只要使用lg(n!)~nlgn次比较就能完成排序, 时间复杂度为O(nlogn),但其空间复杂度为O(n), 因为我们需要定义新数组来临时存储数组变量

转载于:https://www.cnblogs.com/qq1914808114/p/10872608.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值