常用算法之排序算法四【归并排序】

来源:互联网 发布:mac驱动下载 编辑:程序博客网 时间:2024/05/21 09:16

归并排序是将排好序的序列逐步合成一个大序列的算法,从字面上来分析,主要分为归并和排序。

算法描述:

1.申请一块空间,大小为两个排好序序列长度之和,用来存放归并后的序列。

2.设两个指针,分别指向两个已经排好序的序列的起始地址。

3.比较两个指针指向位置的值大小,根据升序降序,选择较小值或者较大值存储在合并空间内,并将相应指针后移。

4.重复3操作,直至指针移至序列尾部。

5.将另一个序列的值全部合并至合并序列中。


先抛开描述,说说自己的理解,就是把一个短有序序列合并成一个新的长有序序列,就是它的主体意思了。一个有序的序列最简单的就是它只有一个元素的序列,它必然有序。两个只有一个元素的序列合并,当然就可以看做是两个有序序列的合并了。依次类推,直至将所有的元素合并到一个序列,排序完成。这里很明显的是需要使用递归的。因为我们将一个大问题分成若干个小问题,自然就想到了分治。

先看看合并:

    public int[] merge(int[] a, int[] b){        int[] array = new int[a.length + b.length];                int i = 0;        int j = 0;        int k = 0;        while ((i < a.length) && (i < b.length)){            if (a[i] < b[i]){                array[k++] = a[i];                i++;            }else {                array[k++] = b[j];                j++;            }        }                while (i < a.length){            array[k++] = a[i++];        }                while (j < b.length){            array[k++] = b[j++];        }        return array;    }

算法简单也比较很高效,时间复杂度处于O(n)级别,再来看看排序,比较麻烦一点的就是讲数组划分成一个个的元素了。其实它也不难:

    if (left < right){            int haft = (left + right)/2;            mergeSort(arr, tmp, left, haft);            mergeSort(arr, tmp, haft + 1, right);           //操作           .....     }
如此,当划分到最后一层就剩下一个元素。再依次返回,就可以得到我们想要的代码了。

    public static <T extends Comparable<? super T>> void mergeSort(            T[] arr, T[] tmp, int left, int right){        if (left < right){            int haft = (left + right)/2;            mergeSort(arr, tmp, left, haft);            mergeSort(arr, tmp, haft + 1, right);            merge(arr, tmp,left,  haft + 1, right);        }    }    public static <T extends  Comparable<? super T>> void merge(            T[] arr, T[] tmp, int lPos, int rPos, int rEnd){        int lEnd = rPos - 1;        int tPos = 0;        while ((lPos <= lEnd) && (rPos <= rEnd)){            if (arr[lPos].compareTo(arr[rPos]) >= 0){                tmp[tPos++] = arr[lPos++];            }else {                tmp[tPos++] = arr[rPos++];            }        }        while (lPos <= lEnd){            tmp[tPos++] = arr[lPos++];        }        while (rPos <= rEnd){            tmp[tPos++] = arr[rPos++];        }        tPos -= 1;        for (int i = 0; tPos >= 0; i++){            arr[rEnd - i] = tmp[tPos--];        }    }

时间复杂度可以算出 O(N) * O(logN) = O(N*logN)。空间复杂度其实并不高,我们只利用一个长度为N 的tmp数组,再无其他辅助空间了。总体看来,无论从空间复杂度还是时间复杂度来说,它都是同高效的。

0 0
原创粉丝点击