重温基础算法内部排序之归并排序法

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重温基础算法内部排序之归并排序法相关的知识,希望对你有一定的参考价值。

内部排序之归并排序法

文章目录


归并排序(Merging sort)是建立在归并操作上的一种有效的排序算法。是采用分治法的一个非常典型的应用。

主要思想

2-路归并排序法

初始序列有n个元素记录,就可以看成 n n n个子序列,每个子序列的长度为 1 1 1,然后前后相邻的序列两两合并,得到 ⌈ n 2 ⌉ \\lceil \\fracn2 \\rceil 2n个长度为 2 2 2或为 1 1 1的有序子序列,在两两合并,直到得到一个长度为n的有序序列为止。

过程演示

递归过程

非递归过程

JAVA代码

非递归实现

package sort;

import java.util.Arrays;

public class MergeSort 
    public static void main(String[] args) throws Exception 
        int[] o = 7, 6, 9, 3, 1, 5, 2, 4, 8;
        System.out.print("排序前: ");
        for (int t : o) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

        // 算法部分
        // 非递归的方式
        nonRecursive(o);

        System.out.print("排序后: ");
        for (int t : o) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

    

    public static void nonRecursive(int[] o) 
        int[] temp = new int[o.length];
        int gap = 1;
        int count = 1;
        while (gap < o.length) 
            for (int i = 0; i < o.length; i = i + 2 * gap) 
                int j = i;
                // 比较的左数组
                int start1 = i;
                int end1 = i + gap - 1;
                // 比较的右数组
                int start2 = i + gap;
                int end2 = i + 2 * gap - 1;

                // 控制越界
                if (start2 >= o.length) 
                    break;
                
                if (end2 >= o.length) 
                    end2 = o.length - 1;
                

                while (start1 <= end1 && start2 <= end2) 
                    if (o[start1] > o[start2]) 
                        temp[j++] = o[start2++];
                     else 
                        temp[j++] = o[start1++];
                    
                

                while (start1 <= end1) 
                    temp[j++] = o[start1++];
                

                while (start2 <= end2) 
                    temp[j++] = o[start2++];
                

                // 将本轮排序结果返回给o数组,
                if (end2 + 1 - i >= 0) 
                    System.arraycopy(temp, i, o, i, end2 + 1 - i);
                

            
            System.out.print("第" + count + "趟,每组元素个数:" + gap + ",排序后: ");
            for (int t : o) 
                System.out.print(t);
                System.out.print(" ");
            
            System.out.println();
            count++;
            gap = 2 * gap;
        
    

    public static int[] sort(int[] sourceArray) 
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        if (arr.length < 2) 
            return arr;
        
        int middle = (int) Math.floor(arr.length / 2);

        int[] left = Arrays.copyOfRange(arr, 0, middle);
        int[] right = Arrays.copyOfRange(arr, middle, arr.length);

        return merge(sort(left), sort(right));
    


    protected static int[] merge(int[] left, int[] right) 
        int[] result = new int[left.length + right.length];
        int i = 0;
        while (left.length > 0 && right.length > 0) 
            if (left[0] <= right[0]) 
                result[i++] = left[0];
                left = Arrays.copyOfRange(left, 1, left.length);
             else 
                result[i++] = right[0];
                right = Arrays.copyOfRange(right, 1, right.length);
            
        

        while (left.length > 0) 
            result[i++] = left[0];
            left = Arrays.copyOfRange(left, 1, left.length);
        

        while (right.length > 0) 
            result[i++] = right[0];
            right = Arrays.copyOfRange(right, 1, right.length);
        

        System.out.print("排序数组:");
        for (int t : result) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

        return result;
    

结果

排序前: 7 6 9 3 1 5 2 4 81趟,每组元素个数:1,排序后: 6 7 3 9 1 5 2 4 82趟,每组元素个数:2,排序后: 3 6 7 9 1 2 4 5 83趟,每组元素个数:4,排序后: 1 2 3 4 5 6 7 9 84趟,每组元素个数:8,排序后: 1 2 3 4 5 6 7 8 9 
排序后: 1 2 3 4 5 6 7 8 9 

递归实现

package sort;

import java.util.Arrays;

public class MergeSort 
    public static void main(String[] args) throws Exception 
        int[] o = 7, 6, 9, 3, 1, 5, 2, 4, 8;
        System.out.print("排序前: ");
        for (int t : o) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

        // 算法部分
        // 递归的方式
        o = sort(o);

        System.out.print("排序后: ");
        for (int t : o) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

    

    public static void nonRecursive(int[] o) 
        int[] temp = new int[o.length];
        int gap = 1;
        int count = 1;
        while (gap < o.length) 
            for (int i = 0; i < o.length; i = i + 2 * gap) 
                int j = i;
                // 比较的左数组
                int start1 = i;
                int end1 = i + gap - 1;
                // 比较的右数组
                int start2 = i + gap;
                int end2 = i + 2 * gap - 1;

                // 控制越界
                if (start2 >= o.length) 
                    break;
                
                if (end2 >= o.length) 
                    end2 = o.length - 1;
                

                while (start1 <= end1 && start2 <= end2) 
                    if (o[start1] > o[start2]) 
                        temp[j++] = o[start2++];
                     else 
                        temp[j++] = o[start1++];
                    
                

                while (start1 <= end1) 
                    temp[j++] = o[start1++];
                

                while (start2 <= end2) 
                    temp[j++] = o[start2++];
                

                // 将本轮排序结果返回给o数组,
                if (end2 + 1 - i >= 0) 
                    System.arraycopy(temp, i, o, i, end2 + 1 - i);
                

            
            System.out.print("第" + count + "趟,每组元素个数:" + gap + ",排序后: ");
            for (int t : o) 
                System.out.print(t);
                System.out.print(" ");
            
            System.out.println();
            count++;
            gap = 2 * gap;
        
    

    public static int[] sort(int[] sourceArray) 
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        if (arr.length < 2) 
            return arr;
        
        int middle = (int) Math.floor(arr.length / 2);

        int[] left = Arrays.copyOfRange(arr, 0, middle);
        int[] right = Arrays.copyOfRange(arr, middle, arr.length);

        return merge(sort(left), sort(right));
    


    protected static int[] merge(int[] left, int[] right) 
        int[] result = new int[left.length + right.length];
        int i = 0;
        while (left.length > 0 && right.length > 0) 
            if (left[0] <= right[0]) 
                result[i++] = left[0];
                left = Arrays.copyOfRange(left, 1, left.length);
             else 
                result[i++] = right[0];
                right = Arrays.copyOfRange(right, 1, right.length);
            
        

        while (left.length > 0) 
            result[i++] = left[0];
            left = Arrays.copyOfRange(left, 1, left.length);
        

        while (right.length > 0) 
            result[i++] = right[0];
            right = Arrays.copyOfRange(right, 1, right.length);
        

        System.out.print("排序数组:");
        for (int t : result) 
            System.out.print(t);
            System.out.print(" ");
        
        System.out.println();

        return result;
    

结果

排序前: 7 6 9 3 1 5 2 4 8 
排序数组:重温基础算法内部排序之希尔排序法

重温基础算法内部排序之冒泡排序法

重温基础算法内部排序之快速排序法

重温基础算法内部排序之快速排序法

重温基础算法内部排序之基数排序法

重温基础算法内部排序之基数排序法