归并排序

来源:互联网 发布:mac系统桌面文件路径 编辑:程序博客网 时间:2024/06/06 23:50

      归并排序是利用归并的思想实现排序,这里只介绍2路归并排序,其思想是:假设初始待排序队列记录数为n,看成n个长度为1的子序列,然后两两合并,得到个长度为2或1的有序子序列,再两两合并,……, 如此重复直至得到长度为n的有序序列为止。示意图如下。

        实现2路归并排序需要额外的与待排序序列大小相同的空间。给出两个有序子序列合并的代码:

/** * 两个有序序列的归并函数 *  * @Title: merge * @Description: 将有序的array[begin,...mid]与 *               array[mid+1,...,end]归并为assist[begin,...,end],最后复制到array * @param array * 待排序数组 * @param assist * 辅助数据 * @param begin           array    [begin--------------mid--------------end] *                     |      |        有序         |      有序       | * @param mid               | *             |             * @param end             assist   [--------------------------------------] *                                 |             有序                     | */private void merge(int[] array, int[] assist, int begin, int mid, int end){int i, j, k;for (i = begin, j = mid + 1, k = begin; (i < mid + 1) && (j <= end); k++){if (array[i] < array[j]){assist[k] = array[i++];} else{assist[k] = array[j++];}}if (i < mid + 1) {for (; i < mid + 1;){assist[k++] = array[i++];}}if (j <= end){for (; j <= end;){assist[k++] = array[j++];}}// copySystem.arraycopy(assist, begin, array, begin, (end - begin + 1));}
       归并排序的递归实现:

/** * 归并排序的实现 *  * @Title: mSort * @Description: array借助于assist把下标从begin到end的序列进行归并排序 * @param array *            待排序序列 * @param assist *            辅助序列 * @param begin *            起始下标 * @param end *            结束下标 */private void mSort(int[] array, int[] assist, int begin, int end){int mid;if (begin == end){return;} else{mid = (begin + end) / 2;mSort(array, assist, begin, mid);mSort(array, assist, mid + 1, end);merge(array, assist, begin, mid, end);}}
/** * 归并排序的主函数 *  * @Title: mergeSort * @Description: 给定待排序数组进行归并排序 * @param array *            给定待排序数组 */public void mergeSort(int[] array){// assist arrayint[] assist = new int[array.length];// sortmSort(array, assist, 0, array.length - 1);}

        非递归实现,其核心思想就是如图所示,第一轮子序列长度为1进行归并,第二轮子序列长度为2进行归并,第三轮子序列长度为4进行归并,····,直至子序列长度大于待排序列的长度。每一轮归并后,剩余序列,分两种情况:1、剩余序列大于当前子序列,则表明剩余有两个序列,进行归并;2、剩余序列小于当前子序列(包括0),则不进行操作。代码如下:

/** * 进行一趟归并排序 *  * @Title: mergePass * @Description: 子序列长度为k,对array序列进行一趟归并操作。 * @param array *            待排序序列 * @param assist *            辅助序列 * @param k *            子序列长度 */private void mergePass(int[] array, int[] assist, int k){int index = 0;while (index < array.length - 2 * k + 1){merge(array, assist, index, (index + k - 1), (index + 2 * k - 1));index += 2 * k;}if (index < array.length - k){merge(array, assist, index, (index + k - 1), array.length - 1);}}

/** * 归并排序非递归实现 *  * @Title: mergeSortNonRec * @Description: 待排序序列array归并排序的非递归操作 * @param array *            待排序序列 */public void mergeSortNonRec(int[] array){// assistint[] assist = new int[array.length];// sortint k = 1;while (k < array.length){mergePass(array, assist, k);k *= 2;}}

      性能分析:

       归并排序是一种稳定的排序算法,每趟归并需要所有记录扫描一遍,耗时O(n)时间,而由完全二叉树深度可知,整个归并排序需要进行次,因此总的时间复杂度为

O(nlogn)。非递归实现时归并排序需要与待排序数组相同的存储空间,递归实现除了上述存储空间,还需要深度为的栈。而且归并排序平均情况、最好情况和最坏情况的时间复杂度都为

         所以,归并排序是一种比较占用内存,但却效率高且稳定的排序算法。

原创粉丝点击