八大排序算法 —— 归并排序

归并排序

归并算法的理解比较难,是一种区别于插入算法,选择算法和交换算法的一种独特算法,需要逐步理解。
核心思想:归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案”修补”在一起,即分而治之)。

图解(网上盗用):
分治法
“分”的步骤:
这里写图片描述
“治”的步骤:
这里写图片描述

详细“治”的步骤:
这里写图片描述
这里写图片描述
这里写图片描述

(1)稳定性
 归并排序是一种稳定的排序。
(2)存储结构要求
 可用顺序存储结构。也易于在链表上实现。
(3)时间复杂度
 对长度为n的文件,需进行趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlgn)。
(4)空间复杂度
  需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序。
注意:若用单链表做存储结构,很容易给出就地的归并排序
归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。

算法实现代码:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int []data  = new int[8];
        for(int i= 0;i<data.length ;i++){
            data[i] = sc.nextInt();
        }
        //归并排序
        mergeSort(data ,0 ,data.length-1);

        for(int i = 0;i<data.length ;i++){
            System.out.print(data[i]+" ");
        }
    }
    //归并排序
    public static int[] mergeSort(int[] data,int low,int high){
        int mid = (low+high)/2;
        if(low<high){
            mergeSort(data,low,mid);
            mergeSort(data,mid+1,high);
            //左右归并
            merge(data,low,mid,high);
        }
        return data;
    }

    //归并排序的辅助方法
    public static void merge(int[] data, int low, int mid, int high) {
        int[] temp = new int[high-low+1];
        int i = low;
        int j = mid+1;
        int k = 0;
        // 把较小的数先移到新数组中
        while(i<=mid && j<=high){
            if(data[i]<data[j]){
                temp[k++] = data[i++];
                //说明:temp[k++] = temp[k] ,只是在temp[k++]之后k的值加1
                //说明:temp[++k] = temp[k+1],temp[++k]之后k的值加1
            }else{
                temp[k++] = data[j++];
            }
        }
        // 把左边剩余的数移入数组
        while(i<=mid){
            temp[k++] = data[i++];
        }
        // 把右边边剩余的数移入数组
        while(j<=high){
            temp[k++] = data[j++];
        }
        // 把新数组中的数覆盖nums数组
        for(int x=0;x<temp.length;x++){
            data[x+low] = temp[x];
        }
    }
}

猜你喜欢

转载自blog.csdn.net/cqx13763055264/article/details/81701419