归并排序算法

归并排序

这是一种非常高效的排序算法,使用到了递归的思想,就算法复杂度而言,和快排是相当的,某些时候,甚至比快排更合适,更高效。

将两个有序数组归并

如果能够实现将两个有序数组归并成一个有序数组,那么可以将4个8个16个N个有序数组归并成一个有序数组,那么对于length为N的数组,也就是N个元素为length为1的有序数组,对其归并也可实现排序,那么如何归并两个有序数组呢,或者说,如果一个数组分别实现了前后两个部分的有序,如何实现整个数组有序?

private Comparable[] aux[] = new Comparable[arr.length];//临时容器

/**
 * arr[low]-arr[mid],arr[mid+1]-arr[high]分别有序,
 * 实现arr[low]-arr[high]有序
 */
private void merge(Comparable[] arr, int low, int mid, int high){
    int i = low;//前半部分的开始索引
    int j = mid + 1;//后半部分的开始索引
    //复制
    for(int k = low; k <= high; k++){
        aux[k] = arr[k];
    }
    for(int k = low; k <= high; k++){
        if(i > mid) arr[k] = arr[j++];//左边用完了,取右边
        else if(j>high) arr[k] = arr[i++];//右边用完了,取左边
        else if(less(aux[i],aux[j])) arr[k] = aux[i++];//左边更小,取左边
        else arr[k] = arr[j++]; //取右边
    }
}

自顶向下的思路

如果一个数组,前半部分和后半部分分别有序,那么可以对数组的两部分顺序进行归并,使整个数组有序。
为了实现一个数组的前半部分有序,那么需要实现它(前半部分)的前后两个部分分别有序,进行归并之后,它可以实现有序。
……
对,这是一个递归。

public void sort(Comparable[] arr){
    sort(arr, 0, arr.length - 1);
}
public void sort(Comparable[] arr, int low, int high){
    if(low >= high) return;
    int mid = low + (high - low) / 2;
    sort(low,mid);//向左递归
    sort(mid+1, high);//向右递归
    merge(arr, mid, high);//归并左右,调用栈栈顶肯定是对单个元素的归并,如arr[10]和arr[11],但是这也是对两个有序数组归并
}

自底向上的思路

对于一个无序的数组,其前两个元素可以看做是数组中有序的两部分,三四个同理…前两个可以归并为一个有序的部分,三四个可以归并为一个有序的部分,这两个部分也可以归并为一个有序的部分,最终前四个元素成为有序的一部分,同理,整个数组也可以归并为一个有序的部分,即实现排序

public void sort(Comparable[] arr){
    for(int size = 1; i < arr.length; size *= 2){
        for(int low = 0; low < arr.length - size; low = low + size * 2)//low由0变成了2
            merge(arr,low,low+size-1, Math.min(low + 2* size - 1, arr.length - 1))//mid可理解为左边排到哪里了,high可以理解为右边排到哪里了
    }
}

总结

算法中应用递归,可以有效地比较与交换,归并排序对于部分有序的数组来说,非常高效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值