博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
归并排序(自顶向下&自底向上)-有图
阅读量:4283 次
发布时间:2019-05-27

本文共 2750 字,大约阅读时间需要 9 分钟。

自顶向下归并排序和自底向上的归并排序

1. 归并排序算法的使用情景

归并排序算法和快速排序算法是java.util.Arrays中使用的排序算。对于一般的基本数据类型,Arrays.sort函数使用双轴快速排序算法,而对于对象类型使用归并排序(准确的说使用的是TimSort排序算法,它是归并排序的优化版本)。这样做的原因有两点,第一个原因,归并排序是稳定的,而快速排序不是稳定的。第二个原因,对于基本数据类型,排序的稳定性意义不大,但对于复合数据类型(比如对象)排序的稳定性就能帮助我们保持排序结果的某些性质。

2. 自顶向下的归并排序

自顶向下的排序算法就是把数组元素不断的二分,直到子数组的元素个数为一个,因为这个时候子数组必定是已有序的,然后将两个有序的序列合并成一个新的有序的序列,两个新的有序序列又可以合并成另一个新的有序序列,以此类推,直到合并成一个有序的数组。

为了体现归并的排序的稳定性,我们的代码使用java的泛型来实现对任意对象的排序。

public static 
> void MergeSortUpToDown(T[] A){
@SuppressWarnings("unchecked") //创建合并两个有序序列的辅助数组 T[] aux = (T[])Array.newInstance(A.getClass().getComponentType(), A.length); mergeSortUpToDown0(A, aux, 0, A.length-1);} public static
> void mergeSortUpToDown0(T[] A, T[] aux, int start, int end){
if(start == end) return; int mid = (start+end)/2; mergeSortUpToDown0(A, aux, start, mid); mergeSortUpToDown0(A, aux, mid+1, end); //复制到辅助数组中,此时[start,mid] [mid+1, end]两个子数组已经有序 System.arraycopy(A, start, aux, start, end - start + 1); //然后归并回来 int i = start, j = mid+1, k; for(k = start; k <= end; k++){
if(i > mid){
A[k] = aux[j++]; }else if(j > end){
A[k] = aux[i++]; }else if(aux[i].compareTo(aux[j]) <= 0){
A[k] = aux[i++]; }else{
A[k] = aux[j++]; } }}

3. 自底向上的归并排序

自底向上的归并排序算法的思想就是数组中先一个一个归并成两两有序的序列,两两有序的序列归并成四个四个有序的序列,然后四个四个有序的序列归并八个八个有序的序列,以此类推,直到,归并的长度大于整个数组的长度,此时整个数组有序。需要注意的是数组按照归并长度划分,最后一个子数组可能不满足长度要求,这个情况需要特殊处理。自顶下下的归并排序算法一般用递归来实现,而自底向上可以用循环来实现。

//自底向上归并排序public static 
> void MergeSortDownToUp(T[] A){
@SuppressWarnings("unchecked") T[] aux = (T[])Array.newInstance(A.getClass().getComponentType(), A.length); int len,i,j,k,start,mid,end; //len表示归并子数组的长度,1表示,一个一个的归并,归并后的长度为2,2表示两个两个的归并,归并后的长度为4,以此类推 for(len = 1; len < A.length; len = 2*len){
//复制到辅助数组中 System.arraycopy(A, 0, aux, 0, A.length); //按照len的长度归并回A数组,归并后长度翻倍 for(start = 0; start < A.length; start = start+2*len){
mid = start + len - 1; //对于数组长度不满足2的x次幂的数组,mid可能会大于end end = Math.min(start + 2*len - 1, A.length-1); i = start; //mid大于end时,j必然大于end,所以不会引起越界访问 j = mid+1; //[start,mid] [mid+1, end] for(k = start; k <= end; k++){
if(i > mid){
A[k] = aux[j++]; }else if(j > end){
A[k] = aux[i++]; }else if(aux[i].compareTo(aux[j]) < 0){
A[k] = aux[i++]; }else{
A[k] = aux[j++]; } } } }}

转载地址:http://esdgi.baihongyu.com/

你可能感兴趣的文章
嵌入式关键字
查看>>
camera (一) 杂谈
查看>>
I2S (二) 总线规范 翻译
查看>>
LCD (一) 杂谈
查看>>
camera(二) DVP接口
查看>>
LCD (二) MCU接口
查看>>
调试器(一) st-link
查看>>
stm32-boot
查看>>
stm32-develop-in-linux
查看>>
SWD(一) 杂谈
查看>>
下载软件 (二) openocd
查看>>
调试器(二) cmsis-dap
查看>>
Git for windows 和 cygwin
查看>>
处理器架构 (一)发展历史
查看>>
处理器架构 (二) RISC与CISC的不同
查看>>
处理器架构 (三) 架构指令集微架构ISA 等概念
查看>>
linux 发行版(一) ubuntu
查看>>
下载软件 (一) JLink_Windows
查看>>
stm32 内存
查看>>
I2S (三) 设备端音频调试方法
查看>>