Java实现归并排序

来源:互联网 发布:通过我的淘宝访问 编辑:程序博客网 时间:2024/05/17 23:23

问题:用归并排序算法对n个对象的数组进行升序排序。

归并排序算法描述(来源于《算法导论》2.3节):

分解:将n个元素分解成各含n/2个元素的字序列;

解决:用归并排序算法对两个子序列递归地排序;

合并:合并两个已排序的字序列得到排序结果。

算法的伪代码描述如下:

其中,A是数组,p是子数组起始位置,也是分解后第一个子数组的起始位置,r是子数组结束位置,也是分解后第二个数组的结束位置,q为分解后第一个数组的结束位置,q+1是分解后第二个数组的起始位置。

伪代码中,p<r,意味着待排序的子数组中至少有两个元素,分解后的两个子数组中各自至少有一个元素;也意味着,如果待排序子数组中只有一个元素时,排序算法什么都不做,这是正确的,因为只有一个元素的数组本身就是有序的;也意味着,分解后的子数组只有一个元素的情况是递归的基本情况,递归在这时停止。


对两个有序的子数组合并的过程是这样的:比较两个子数组左边的元素,哪个元素小,就把它取出来并放进大数组中;不断重复上诉过程,直到其中一个数组的元素取完了;然后,依次取出未取完数组中的元素放在大数组的后面。

合并两个有序的子数组的Java源码如下:

@SuppressWarnings("unchecked")private <T extends Comparable<T>> void merge(T[] a, int p, int q, int r) {// 获得数组left的长度int n1 = q - p + 1;// 获得数组right的长度int n2 = r - q;// 创建数组leftT[] left = (T[]) Array.newInstance(a.getClass().getComponentType(), n1);// 创建数组rightT[] right = (T[]) Array.newInstance(a.getClass().getComponentType(), n2);        // 把数组a的相应值赋给leftfor(int i = 0; i < n1; i++){        left[i] = a[p + i];        }// 把数组a的相应值赋给right        for(int i = 0; i < n2; i++){        right[i] = a[q + 1 + i];        }        // left数组当前待处理元素的位置        int i = 0;        // left结束标识        boolean endLeft = false;        // right数组当前待处理元素的位置        int j = 0;        // right结束标识        boolean engRight = false;        int k = p;        while(k <= r){        if (left[i].compareTo(right[j]) < 0) {a[k] = left[i];// 说明left的最后一个元素已被处理if (i == (n1 - 1)) {endLeft = true;k++;break;}i++;} else {a[k] = right[j];// 说明right的最后一个元素已被处理if (j == (n2 - 1)) {engRight = true;k++;break;}j++;}        k++;        }        // 把还没处理完的数组的剩余元素放进a中        if (endLeft) {while(k <= r){a[k] = right[j];k++;j++;}} else {while(k <= r){a[k] = left[i];k++;i++;}}}

归并排序算法Java源代码如下:

@Overridepublic <T extends Comparable<T>> void sort(T[] a) {// TODO Auto-generated method stub// 默认情况下,对数组从头到尾排序int p = 0;int r = a.length - 1;sort(a, p, r);}private <T extends Comparable<T>> void sort(T[] a, int p, int r) {// TODO Auto-generated method stubif (p < r) {int q = (p + r) / 2;sort(a, p, q);sort(a, q + 1, r);merge(a, p, q, r);}}

根据算法描述和代码执行过程,我们可以清晰看到,递归过程先是对问题不断的分解,直到子数组中只有一个元素为止(如下图中的从上到下的过程),然后从只有一个元素的数组开始,对子数组进行合并(如下图中德自下而上的过程)。


0 0
原创粉丝点击