常用排序算法-归并排序(分治法)

本文详细介绍了归并排序的原理及实现过程,通过实例演示了如何使用分治法将数组逐步拆分并排序,最终合并为有序数组。文章还提供了一个Java实现的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      归并排序(分治法)

    归并排序,其实是采用常用的算法-分治法来实现的。 所谓的“分”,就是将一个问题分成很多小的问题来进行递归求解; "治",将各个阶段的小问题得到的答案,合并在一起,修补好,即所谓的分而治之。

下面我们来举一个简单的例子:

    我们将排序一个数组:{5,2,1,4,6,8,3,7}

                  拆分阶段1:{5,2,1,4}, {6,8,3,7}

                  拆分阶段2:{5,2}, {1,4}, {6,8},{3,7}

              处理拆分结果:{2,5}, {1,4}, {6,8},{3,7}

                  归并阶段1:{1,2,4,5},{3,6,7,8}

                  此时,我们可以得到两个有序的子序列,现在我们需要将这两个有序的子序列进行排序。

                  归并阶段2:

                    {1,2,4,5,3,6,7,8}  

                   生命一个新的数组,存储最后的结果数组,比较子序列,值小的子序列指针右移:

                   ①. 1 < 3  ,1将存入新数组,并且左边子序列指针右移 =》新数组:{1}  

                   ②. 2 < 3  ,  2将存入新数组,并且左边子序列指针右移 =》新数组:{1,2} 

                   ③. 4 < 3  ,  3将存入新数组,并且右边子序列指针右移 =》新数组:{1,2,3}

                   ④. 4 < 6  ,  4将存入新数组,并且左边子序列指针右移 =》新数组:{1,2,3,4}

                   ⑤. 5 < 6  ,  5将存入新数组,并且左边子序列指针右移 =》新数组:{1,2,3,4,5}  

                   ⑥. 最后将右边剩余的6,7,8依次存入新数组 =》新数组:{1,2,3,4,5,6,7,8}  

其实,java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。

代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {
    public static List<int[]> mergeArr = new ArrayList<int[]>();
    public static int len;
    
    public static void main(String[] args) {
        Test test = new Test();
        int []arr = {9,8,7,6,5,4,3,2,1};
        len = arr.length;
        test.points(arr);
        arr = test.merge();
        System.out.println();
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i]+" ");
        }
    }
    
    /**
     * 分
     * @param
     * @return
     */
    public void points(int[] arr){
        if(arr.length == 1){
            mergeArr.add(arr);
            return;
        }
        
        if(arr.length == 2){
            Arrays.sort(arr);
            mergeArr.add(arr);
            return;
        }
        
       int arr1[];
       int arr2[];
       if(judgeParity(arr.length) == 1){
           arr1 = new int[arr.length / 2 + 1];
           arr2 = new int[arr.length / 2];
           arr1 = arrayTransfer(0, arr.length / 2, arr);
           arr2 = arrayTransfer(arr.length / 2 + 1, arr.length -1, arr);
       }else{
           arr1 = new int[arr.length / 2];
           arr2 = new int[arr.length / 2]; 
           arr1 = arrayTransfer(0, arr.length / 2 - 1 , arr);
           arr2 = arrayTransfer(arr.length / 2, arr.length -1, arr);
       }
       
       points(arr1);
       points(arr2);
    }
    
    /**
     * 合
     * @param
     * @return
     */
    public int[] merge(){
        int arr[] = new int[len];
        int n = 0;
        for(int i=0; i<mergeArr.size(); i++){
            for(int j=0; j<mergeArr.get(i).length; j++){
                arr[n] = mergeArr.get(i)[j];
                n++;
            }
        }
        
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i]+" ");
        }
        Arrays.sort(arr);
        return arr;
    }
    
    /**
     * 判断长度奇偶
     * @param
     * @return
     */
    public int judgeParity(int length){
        if(length%2 == 0){
            return 2;
        }else{
            return 1;
        }
    }
    
    /**
     * 数组转移
     * @param start 起始坐标,end 结束坐标
     * @return
     */
    public int[] arrayTransfer(int start, int end, int[] arr){
        int length = end - start + 1;
        int[] newArr = new int[length];
        int j=0;
        for(int i=start; i<=end; i++){
            newArr[j] = arr[i];
            j++;
        }
        return newArr;
    }

}


 希望小编写的东西对大家有所帮助,助大家学有所成。



 

                  

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值