归并排序

来源:互联网 发布:网络成瘾临床诊断标准 编辑:程序博客网 时间:2024/06/11 19:37
  • 思想:将两个或两个以上的有序序列合并成一个新的有序序列。具体说来就是先把待排序的 n个元素序列分解成两个子序列, 每个子序列包括 n/2个元素,不断重复这个过程,直到分解成n个长度为1的子序列;再对每个子序列进行合并排序, 不断重复这个过程,直到整个序列有序。
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(n)
  • 优化:1.在数组长度比较短时,不再进行递归,而是选择其他排序方案:如插入排序等,以达到最优时间复杂度;2.归并过程中,可以用记录数组下标的方式代替申请新内存空间,避免原数组和辅助数组频繁的数据读写,经此优化,空间复杂度能达到O(1)。
  • 注意:1.归并排序的最好、最坏以及平均时间复杂度都是O(nlogn);2.归并排序算法比较占用内存,空间复杂度为O(n),但却是效率高且稳定的排序算法;3.归并排序是一种稳定的排序算法。
  • 代码如下:

1.不含注释

public class MergeSort {    public static void mergeSort(int [] a) {        Sort(a, 0, a.length-1);    }    public static void Sort(int [] a, int left, int right) {        if (left < right) {            int mid = (left+right)/2;            Sort(a, left, mid);            Sort(a, mid+1, right);            Merge(a, left, mid, right);        }    }    public static void Merge(int [] a, int left, int mid, int right) {        int [] temp = new int[a.length];        int i = left;        int j = mid+1;        int k = 0;        while (i <= mid && j <= right) {            if (a[i] < a[j]) {                temp[k++] = a[i++];            } else {                temp[k++] = a[j++];            }        }        while (i <= mid) {            temp[k++] = a[i++];        }        while (j <= right) {            temp[k++] = a[j++];        }        for (i = 0; i < k; i++) {            a[left+i] = temp[i];        }    }    public static void print(int[] a) {        for (int i = 0; i < a.length; i++) {            System.out.print(a[i]+" ");        }    }    public static void main(String[] args) {        int [] data = {88,22,27,19,10,37,63,28,33,54};        System.out.println("归并排序前的数组:");        print(data);        System.out.println();        mergeSort(data);        System.out.println("归并排序后的数组:");        print(data);    }}

2.含注释详解

/** * * @author artadonis * */public class MergeSort {    public static void mergeSort(int [] a) {        //归并排序,数组下标范围:0~a.length-1        Sort(a, 0, a.length-1);    }    public static void Sort(int [] a, int left, int right) {        //分解条件:left<right时才分解,当left>=right的时候,说明已经分解到单个元素了        if (left < right) {            //找出中间索引            int mid = (left+right)/2;            //对左半部分数组递归进行分解与合并            Sort(a, left, mid);            //对右半部分数组递归进行分解与合并            Sort(a, mid+1, right);            //在递归外:在调用这条语句时,说明左右两边数组已经分别有序            //在递归内:已分解成单个元素,可视作有序,开始进行合并            Merge(a, left, mid, right);        }    }    //left是数组中要排序的开始索引,排序不一定是从0开始    //Merge(a, left, mid, right),只是对数组的子数组a[left...right]排序    public static void Merge(int [] a, int left, int mid, int right) {        //定义一个与带排序序列长度相同的临时数组        int [] temp = new int[a.length];        //i,j变量首先分别指向两数组的句首元素        int i = left;        int j = mid+1;        int k = 0;        //i和j变量所指向的数组,到达尾端了,就跳出循环        //if...else语句中,哪个小就把哪个放在临时数组中        while (i <= mid && j <= right) {            if (a[i] < a[j]) {                temp[k++] = a[i++];            } else {                temp[k++] = a[j++];            }        }        //将剩余部分依次放入临时数组中        while (i <= mid) {            temp[k++] = a[i++];        }        while (j <= right) {            temp[k++] = a[j++];        }        //不理解分解、治理、再合并这个递归过程的话,可以把以下三条语句的移出注释,打印输出结果,以助理解        //      System.out.print("temp数组:  ");        //      print(temp);        //      System.out.println();        //因为k在上面多加了一次,所以此时是i<k(就已经是原来数组的长度0~‘k’),而不是i<=k        //合并完成后,把此时已经有的临时数组temp[],拷贝回原数组a[],i变量是初始化过的局部变量,需要更改的时候不要再加数据类型,直接更改就行        for (i = 0; i < k; i++) {            a[left+i] = temp[i];        }        //不理解分解、治理、再合并这个递归过程的话,可以把以下三条语句的移出注释,打印输出结果,以助理解        //      System.out.print("a数组:  ");        //      print(a);        //      System.out.println();    }    //合并完成后,把此时已经有的临时数组temp[],拷贝回原数组a[],i变量是初始化过的局部变量,    //需要更改的时候不要再加数据类型,直接更改就行    public static void print(int[] a) {        for (int i = 0; i < a.length; i++) {            System.out.print(a[i]+" ");        }    }    public static void main(String[] args) {        int [] data = {88,22,27,19,10,37,63,28,33,54};        System.out.println("归并排序前的数组:");        print(data);        System.out.println();        mergeSort(data);        System.out.println("归并排序后的数组:");        print(data);    }}
1 0
原创粉丝点击