排序3(Java)

1.归并排序

1.1归并排序的原理

两个数组归并的过程:首先借助一个临时空间来保存数组,在两个有序数组搞两个下标,比较两个下标的大小,谁小就把谁放在临时空间,顺便把下标往后移。
在这里插入图片描述

因为是原地排序,因此在最后把数组要拷贝到原数组。
归并排序的前提是两边必须都有序,那怎么办呢?为了保证数组有序,因此继续往下切分,切分到只剩下一个元素,就称为有序的数组了。然后按照上述相同的步骤,比较两个有序区间元素的大小,然后继续拷贝回去,之后,比较下一组的数据,以及类推。
在这里插入图片描述

1.2归并排序的实现(递归)

import java.util.Arrays;
public class Sort {
public static void mergeSort(int [] arr){
        _mergeSort(arr,0,arr.length);
    }

    //辅助递归的方法
    public static void _mergeSort(int [] arr,int left,int right) {
       if(right-left<=1) {
           //没有元素或者只有一个元素
           //不需要做任何处理
           return ;
       }
       int mid=(left+right)/2;
       _mergeSort(arr,left,mid);
       _mergeSort(arr,mid,right);
       merge(arr,right,left,mid);
    }

    //归并排序中的关键操作,就是归并两个有序数组
    //使用该merge方法完成数组归并的过程
    //此处两个数组就通过left,mid ,right来描述
    //[left,mid)左侧区间
    //[mid,right)右侧区间
    public static void merge(int [] arr,int right,int left,int mid){
        //在代码中进行具体的归并排序
        //需要创建一个临时的空间来保存归并的结果
        //临时空间得保存的下两个数组
        //right-left
        int [] tmp=new int[right-left];
        //这个下标表示当前元素放到临时空间的哪个位置上
        int tmpIndex=0;
        int cur1=left;
        int cur2=mid;
        while(cur1<mid&&cur2<right){
            //目的是为了稳定性
            if(arr[cur1]<=arr[cur2]){
                //把cur1对应的元素放到临时空间中
                tmp[tmpIndex]=arr[cur1];
                tmpIndex++;
                cur1++;
            }else{
                //把cur对应的元素插到临时空间中
                tmp[tmpIndex]=arr[cur2];
                tmpIndex++;
                cur2++;
            }
        }
        //循环换结束之后,需要把剩余的元素也拷贝到最终的结果
        while(cur1<mid){
            tmp[tmpIndex]=arr[cur1];
            tmpIndex++;
            cur1++;
        }
        while(cur2<right){
            tmp[tmpIndex]=arr[cur2];
            tmpIndex++;
            cur2++;
        }
        //还需要把tmp的结果放到arr数组,原地排序
        //把原始数组的[left,right]填满
        for(int i=0;i<tmp.length;i++){
            arr[left+i]=tmp[i];
        }
    }

    public static void swap(int [] arr,int i,int j){
        int tmp=arr[i];
        arr[i]=arr[j];
        arr[j]=tmp;
    }

    public static void main(String[] args) {
        int [] arr={9,5,2,7,3,6,8};
       mergeSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

归并排序的时间复杂度为O(NlogN),空间复杂复杂度为O(N),稳定性:稳定排序。

1.3归并排序的实现(非递归)

import java.util.Arrays;
public class Sort {
//非递归实现归并排序
    //直接把[0] [1]视为带归并的数组
    public static void mergeSortByLoop(int [] arr){
        //gap用于限定分组
        //gap指的含义每个待归并数组的长度
        int gap=1;
        for(;gap<arr.length;gap=gap*2){
            //当前两个带归并的数组
            for(int i=0;i<arr.length;i=i+2*gap){
                //折个循环中控制两个相邻的数组进行归并
                int left=i;
                int mid=i+gap;
                if(mid>=arr.length){
                    mid=arr.length;
                }
                int right=i+2*gap;
                if(right>=arr.length){
                    right=arr.length;
                }
                merge(arr,right,left,mid);
            }
        }
    }

    public static void merge(int [] arr,int right,int left,int mid){
        //在代码中进行具体的归并排序
        //需要创建一个临时的空间来保存归并的结果
        //临时空间得保存的下两个数组
        //right-left
        if(left>=right){
            return;
        }
        int [] tmp=new int[right-left];
        //这个下标表示当前元素放到临时空间的哪个位置上
        int tmpIndex=0;
        int cur1=left;
        int cur2=mid;
        while(cur1<mid&&cur2<right){
            //目的是为了稳定性
            if(arr[cur1]<=arr[cur2]){
                //把cur1对应的元素放到临时空间中
                tmp[tmpIndex]=arr[cur1];
                tmpIndex++;
                cur1++;
            }else{
                //把cur对应的元素插到临时空间中
                tmp[tmpIndex]=arr[cur2];
                tmpIndex++;
                cur2++;
            }
        }
     //循环换结束之后,需要把剩余的元素也拷贝到最终的结果
        while(cur1<mid){
            tmp[tmpIndex]=arr[cur1];
            tmpIndex++;
            cur1++;
        }
        while(cur2<right){
            tmp[tmpIndex]=arr[cur2];
            tmpIndex++;
            cur2++;
        }
        //还需要把tmp的结果放到arr数组,原地排序
        //把原始数组的[left,right]填满
        for(int i=0;i<tmp.length;i++){
            arr[left+i]=tmp[i];
        }
    }
	public static void main(String[] args) {
        int [] arr={9,5,2,7,3,6,8};
       mergeSortByLoop(arr);
        System.out.println(Arrays.toString(arr));
    }
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值