归并排序

归并排序 O(Nlogn)

归并排序的思路是:将要排序的数组先递归分为一个一个的,长度为1的小数组,再通过递归合并起来,在合并的过程中,先开辟一个新的数组空间,通过同时遍历两个老数组的每个元素(此时两个数组已经是有序的了),不断地给新空间赋值来达到重新排序的效果。可以理解为变交换元素为赋值,再加上递归来实现。
package cn.stu.test;

import java.util.Arrays;

public class Test{

    public static void merge(int[] arr,int left,int mid,int right){
        int[] arr_temp = new int[arr.length];//此处也可以赋值数组长度为(right-left+1)
        int left_temp = left;
        int mid_temp = mid;
        int i = 0;
        while((left_temp<=mid)&&(mid_temp+1<=right)){
            if(arr[left_temp] > arr[mid_temp+1]){
                arr_temp[i] = arr[left_temp];
                i++;
                left_temp++;
            }else{
                arr_temp[i] = arr[mid_temp+1];
                i++;
                mid_temp++;
            }
        }
        while(left_temp<=mid){
            arr_temp[i] = arr[left_temp];
            i++;
            left_temp++;
        }
        while(mid_temp+1<=right){
            arr_temp[i] = arr[mid_temp+1];
            i++;
            mid_temp++;
        }
        for(int j=0;j<i;j++){
            arr[left+j] = arr_temp[j];
        }
    }

    public static void sort_merge (int[] arr,int left,int right){
        if(left<right){
            int temp =(left+right)/2;//left和right太大时要防止越界
            sort_merge(arr,left,temp);
            sort_merge(arr,temp+1,right);
            merge(arr,left,temp,right);
        }
    }

    public static void main(String[] args) {
        int[] arr_temp = {1,3,4,2,9,5,43,5,6,7,44};
        sort_merge(arr_temp,0,arr_temp.length-1);
        System.out.println(Arrays.toString(arr_temp));
    }
}
改进的递归排序:
方法一:
将sort_merge方法改为如下的方式,就是加上一个判断,通过这个判断在适当的时候(就是要进行排序的子数组是有序的时候)可以直接跳过去,从而提高效率
public static void sort_merge (int[] arr,int left,int right){
        if(left<right){
            int temp =(left+right)/2;//left和right太大时要防止越界
            sort_merge(arr,left,temp);
            sort_merge(arr,temp+1,right);
            if(arr[temp] < arr[temp+1])
                merge(arr,left,temp,right);
        }
    }
方法二:
基于插入排序对于小规模数组的排序更具优势,所以我们可以采用归并加上插入的方式,先递归,将大数组分为一些小数组,再通过插入来处理,最后再通过递归合起来。
public static void sort_merge(int[] arr, int left, int right) {
        if (left < right) {
            if(right-left <= 5){//5是自己设置的,根据实际情况改变
                sort_insert(arr, left, right);
                return;
            }
            int temp = (left + right) / 2;// left和right太大时要防止越界
            sort_merge(arr, left, temp);
            sort_merge(arr, temp + 1, right);
            if (arr[temp] < arr[temp + 1])
                merge(arr, left, temp, right);
        }
    }
插入排序的代码如下所示:
public static void sort_insert(int[] arr, int left, int right) {

        for (int i = left + 1; i <= right; i++) {
            int j = i;
            while ((j >= left + 1) && (arr[j] > arr[j - 1])) {
                int temp = arr[j - 1];
                arr[j - 1] = arr[j];
                arr[j] = temp;
                j--;
            }
        }
    }
以上的归并排序采用的是自顶向下的排序方式,也可以采用自底向上的排序方式,跳过将数组拆分的步骤,直接从一个一个的小数组的合并开始。
public static void sortMergeDownToUp(int[] arr){
        for(int i=1;i<=arr.length;i+=i){
            for(int j=0;j<arr.length-i;j+=i+i){
                merge(arr, j, j+i-1, Math.min(j+2*i-1, arr.length-1));
            }
        }
    }

外循环从1,2,4,8,16….开始逐次合并小数组;
内循环注意循环的增量不大一样,还有要注意防止数组越界,例如判断条件和合并的最右值都要额外考虑;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值