算法--归并排序

来源:互联网 发布:网络市场中间商的类型 编辑:程序博客网 时间:2024/06/14 08:27

1、基本概念

归并排序是将n个记录看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,最终合成一个有序序列。
这里写图片描述
将数组对半拆分,一直拆分到只有一个元素。然后做归并操作。
归并操作:
创建一个临时数组,然后将两个元素较小值先放入临时数组,再放次小者,将临时数组的内容赋给原数组。循环整个数组
再次创建临时数组,将数组四个四个进行操作,先放最小者,再放次小者。循环整个数组。直到进行整个数组的操作

2、实现

2.1 非递归方式

public static void main(String[] args) {    int[] src = { 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9 };    mergeSort(src);    print(src);}public static void mergeSort(int[] a){    int len = 1;    while(len < a.length){        //将数组分为len为一组,分别进行归并        for(int i = 0; i < a.length; i += 2*len){            merge(a, i, len);        }        //将归并步长*2        len *= 2;    }}//归并操作public static void merge(int[] a, int i, int len){    int start = i;    int m = i + len;//归并的前半部分数组    int j = i + len;    int n = j +len;//归并的后半部分数组    int[] temp = new int[2*len];    int count = 0;    //将前半段和后半段中比较小的值放入temp数组    //因为都是较小值放入temp 所以数组变有序 排序的主要实现    while(i < m && j < n && j < a.length){        if(a[i] <= a[j])            temp[count++] = a[i++];        else            temp[count++] = a[j++];    }    //将前半段剩余的部分放入temp数组    while(i < m && i < a.length)        temp[count++] = a[i++];    //将后半段剩余的部分放入数组    while(j < n && j < a.length)        temp[count++] = a[j++];    count = 0;    //将temp数组中的内容放入待排序的数组,start为传入的起始位置    while(start < temp.length && start < a.length)        a[start++] = temp[count++];}public static void print(int src[]){    for (int i = 0; i < src.length; i++) {        System.out.print(src[i] + "  ");    }    System.out.println();}

2.2 递归方式

public static void main(String[] args) {    int[] src = { 3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9 };    mergeSort(src, 0, src.length-1);    print(src);}public static void mergeSort(int[] data,int left,int right){    if(left<right) {//如果传入的左下标小于右下标 返回        int half = (left + right) / 2;        mergeSort(data, left, half);//对前半部分进行递归拆分        mergeSort(data, half + 1, right);//对前半部分进行递归拆分        merge(data, left, right);//归并    }}public static void merge(int []a, int low, int high) {    int mid = (low + high) / 2;    int i = low;    int j = mid + 1;    int count = 0;    int temp[] = new int[high - low + 1];    //归并前后部分较小者  排序在此方法中完成    while (i <= mid && j <= high) {        if (a[i] < a[j]) {            temp[count++] = a[i++];        } else {            temp[count++] = a[j++];        }    }    //归并前半部分剩余者    while (i <= mid) {        temp[count++] = a[i++];    }    //归并后半部分剩余者    while (j <= high) {        temp[count++] = a[j++];    }    //赋值给原数组    count = 0;    while (low <= high) {        a[low++] = temp[count++];    }}public static void print(int src[]){    for (int i = 0; i < src.length; i++) {        System.out.print(src[i] + "  ");    }    System.out.println();}

3、复杂度

两两归并,扫描整个数组的复杂度为O(n)。而归并操作类似树结构,所以总共需要logn次。所以总的复杂度为O(nlogn)
空间复杂度为O(n)
归并是稳定的排序方法

原创粉丝点击