算法:用Java实现归并排序(MergeSort)

本文我准备用Java实现归并排序。具体的排序算法过程已经在注释里面了,大家可以复制代码到IDE里面,用DEBUG模式研究算法的过程(算法参考:https://blog.csdn.net/qq_36442947/article/details/81612870):

import java.util.Arrays;
import java.util.Random;

/**
 * @author LiYang
 * @ClassName MergeSort
 * @Description 归并排序算法
 * @date 2019/11/4 16:50
 */
public class MergeSort {

    /**
     * 归并排序算法(MergeSort)
     * 本算法会分解数组到左右都只有1个元素的子数组(肯定有序),
     * 然后归并为2个元素的子数组(已经有序),然后又归并为
     * 4个元素的子数组(已经有序)……直到全部待排序数组
     * @param arr 待排序的数组
     * @param left 起始下标
     * @param right 终止下标
     */
    public static void mergeSort(int [] arr, int left, int right){
        //当子序列中只有一个元素时,也就是left = right时,结束递归
        if(left < right){
            //将当前数组分为两个子数组的分界线
            int mid = (left + right) / 2;

            //对左侧子数组进行递归归并排序
            mergeSort(arr, left, mid);

            //对右侧子数组进行递归归并排序
            mergeSort(arr, mid + 1, right);

            //归并左右侧子序列
            merge(arr, left, mid, right);
        }
    }

    /**
     * 归并排序算法的归并操作,将两个有序数组归并为一个排序数组
     * @param arr 归并前的数组,包含左右两个有序数组
     * @param left 左边界
     * @param mid 两个有序数组的分隔下标
     * @param right 右边界
     */
    public static void merge(int[] arr, int left, int mid, int right){
        //左边数组检测的下标
        int leftIndex = left;
        
        //右边数组检测的下标
        int rightIndex = mid + 1;
        
        //归并后的数组的下标
        int mergeIndex = left;

        //归并排序装归并结果的数组
        int [] mergeArray = new int[arr.length];

        //当左数组和右数组都未到最右边
        while(leftIndex <= mid && rightIndex <= right){
            
            //如果左数组的元素小于等于右数组的元素
            if(arr[leftIndex] <= arr[rightIndex]) {
                
                //将左数组的元素放入归并后的数组,左数组index + 1
                mergeArray[mergeIndex++] = arr[leftIndex++];
                
            //如果左数组元素大于右数组元素
            } else {
                
                //将右数组的元素放入归并后的数组,右数组index + 1
                mergeArray[mergeIndex++] = arr[rightIndex++];
            }
        }//本while循环结束,左右数组至少有一个遍历结束

        //如果左数组没有遍历结束
        while(leftIndex <= mid){
            //将左数组剩下的元素依次放入归并后的数组
            mergeArray[mergeIndex++] = arr[leftIndex++];
        }
        
        //如果右数组没有遍历结束
        while(rightIndex <= right){
            //将右数组剩下的元素依次放入归并后的数组
            mergeArray[mergeIndex++] = arr[rightIndex++];
        }

        //将归并后的有序数组,复制代替原来的数组
        for (int i = left; i <= right; i++){
            arr[i] = mergeArray[i];
        }
    }

    /**
     * 归并排序(MergeSort)的驱动程序
     * @param arr 待排序的数组
     */
    public static void mergeSort(int[] arr){
        //归并排序的左边界
        int left = 0;

        //归并排序的右边界
        int right = arr.length - 1;
        
        //调用归并排序的方法
        mergeSort(arr, left, right);
    }

    /**
     * 验证归并排序算法
     * @param args
     */
    public static void main(String[] args) {
        //待排序数组
        int[] arr = new int[30];

        //随机数类
        Random random = new Random();

        //随机生成排序数组(100以内的整数)
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(100);
        }

        //打印待排序数组
        System.out.println("归并排序前:" + Arrays.toString(arr));

        //进行归并排序(调用驱动程序,就是只有一个参数的mergeSort()方法)
        mergeSort(arr);

        //打印归并排序后的数组
        System.out.println("归并排序后:" +Arrays.toString(arr));
    }
    
}

运行 MergeSort 类的main方法,归并排序算法测试通过:

归并排序前:[33, 39, 17, 51, 8, 28, 92, 93, 30, 52, 25, 45, 36, 52, 4, 89, 67, 23, 42, 29, 59, 50, 18, 82, 37, 59, 32, 48, 12, 51]
归并排序后:[4, 8, 12, 17, 18, 23, 25, 28, 29, 30, 32, 33, 36, 37, 39, 42, 45, 48, 50, 51, 51, 52, 52, 59, 59, 67, 82, 89, 92, 93]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章