JAVA实践归并排序

来源:互联网 发布:json在线格式化 php 编辑:程序博客网 时间:2024/05/29 04:52

前言

参考书籍:
《数据结构与算法分析·C语言描述》
《算法·第4版》

归并排序只有两大难点,一是分,二是并。

合并

    static void merge(int[] a, int low, int mid, int high) {        int i = low, j = mid + 1;        for (int k = low; k <= high; k++) {            aux[k] = a[k];        }        for (int k = low; k <= high; k++) {            if (i > mid) a[k] = aux[j++];            else if (j > high) a[k] = aux[i++];            else if (aux[i] > aux[j]) a[k] = aux[j++];            else a[k] = aux[i++];        }    }

上面这是合并的代码,其中aux是对原始数据的备份,a是我们需要归并的数组。

假设我们有数组

int a = new int[]{3, 6, 4, 5}

那我们传入的参数是merge(a, 0, 1, 3);
四个参数中,mid表示以其为界,左边和右边的数组都是有序的。

[3, 6] | [4, 5]

进行合并操作时,我们分别选取两个数组的第一个元素来比较,然后取较小者。
即代码中

int i = low, j = mid + 1;

以及

for (int k = low; k <= high; k++) {        if (i > mid) a[k] = aux[j++];        else if (j > high) a[k] = aux[i++];        else if (aux[i] > aux[j]) a[k] = aux[j++];        else a[k] = aux[i++];    }

从第一个元素low到最后一个元素high进行归并操作,i和j会有四种情况。

分别是左边数组元素已经取尽、右边数组元素已经取尽、左边数组元素大于右边数组元素、左边数组元素小于右边数组元素。

拆分

拆分用递归实现还是比较简单的,只需要计算中间的位置在哪,然后通过参数调整即可。

    static void mergeSort(int[] a, int low, int high) {        if (low >= high) {            return;        }        int mid = low + (high - low) / 2;        //拆分左边        mergeSort(a, low, mid);        //拆分右边        mergeSort(a, mid + 1, high);        //merge(a, low, mid, high);    }

完整代码

public class MergeDemo {    //产生测试数据的个数    static int maxNum = 200000;    static int[] testData = new int[maxNum];    static int[] aux = new int[maxNum];    static void init() {        for (int i = 0; i < maxNum; i++) {            testData[i] = (int) (Math.random() * maxNum + 1);        }    }    public static void main(String[] args) {        long start, end;        init();        int[] a = testData.clone();        start = System.currentTimeMillis();        mergeSort(a);        end = System.currentTimeMillis();        System.out.println(end - start + "ms");    }    static void mergeSort(int[] a) {        sort(a, 0, a.length - 1);    }    static void sort(int[] a, int low, int high) {        if (low >= high) {            return;        }        int mid = low + (high - low) / 2;        sort(a, low, mid);        sort(a, mid + 1, high);        merge(a, low, mid, high);    }    static void merge(int[] a, int low, int mid, int high) {        int i = low, j = mid + 1;        for (int k = low; k <= high; k++) {            aux[k] = a[k];        }        for (int k = low; k <= high; k++) {            if (i > mid) a[k] = aux[j++];            else if (j > high) a[k] = aux[i++];            else if (aux[i] > aux[j]) a[k] = aux[j++];            else a[k] = aux[i++];        }    }}

结果

66ms

最后,归并排序是可以用插入排序优化的,但是,我尝试的优化在数量级为百万级别时,就少那么几十毫秒,而当数字达到千万级别时,更耗时了。。可能是学艺不精,就不贴代码了。

END

0 0