归并排序原理及Java实现
来源:互联网 发布:祖传秘方淘宝可以卖吗 编辑:程序博客网 时间:2024/06/06 09:18
归并排序是基于归并操作的一种效率较高的排序算法,同快速排序一样,归并排序也是分治法的一种应用。其时间复杂度为:O(nlogn),最好和最坏情况下都是O(nlogn)。空间复杂度为O(n)。归并排序是一种稳定的排序算法(两个相等的数据,在排序后其先后顺序不变,因为归并不涉及两个相等的数据进行交换)。
归并排序的思想
归并排序的思想就是将待排序数列num[n]看做是n个有序数列,然后将相邻的有序表进行归并。归并排序其实就是做两件事:
(1)分解:将待排序数列进行折半划分;
(2)归并:将划分后的序列段和并排序。
例如:有一待排序序列nums[14, 12, 15, 13, 11, 16],下图是其分解和归并过程:
我们首先来分析第二步归并过程。
合并两个有序数列
要想合并两个有序数列很简单,只需要比较两个数列的第一个数,然后取最小的,然后移动被取的那个数列的指针。直到有一个数列取完指针为空,然后再把另一个不为空的数列复制过去。
核心代码为:
//合并有序数组序列,利用辅助数组。 public static void merge(int[] nums, int left, int mid, int right, int[] result) { int left1 = left; int right1 = mid; int left2 = mid + 1; int right2 = right; int k = 0; //先把较小的数移入到临时数组 while (left1 <= right1 && left2 <= right2) { if (nums[left1] <= nums[left2]) { result[k++] = nums[left1++]; } else { result[k++] = nums[left2++]; } } //把左边剩余的数移入 while (left1 <= right1) { result[k++] = nums[left1++]; } //把右边剩余的数移入 while (left2 <= right2) { result[k++] = nums[left2++]; } //将排序好的覆盖到nums数组 for (int i = 0; i < k; i++) { nums[left + i] = result[i]; } }从上边代码中可以看到,我们用了一个临时数组来存储排序好的数据,所以归并排序的空间复杂度为O(n)。合并的时间度是O(n)。
分析完归并后,我们再来看分解。第一步:先把原始数列除以2分为A,B两个部分,然后再将A,B各自一分为二,重复此过程,直到数列只有一个数据了,这意味着这个数列是有序的。可以明显看到,这个过程是一个递归过程,所以用递归方法实现。
归并排序的核心代码
public class MergeSort { //将待排序数组分解 public static void mergeSort(int[] nums, int left, int right, int[] result) { if (left < right) { int mid = (left + right) / 2; mergeSort(nums, left, mid, result); mergeSort(nums, mid + 1, right, result); merge(nums, left, mid, right, result); } } //合并有序数组序列,利用辅助数组。 public static void merge(int[] nums, int left, int mid, int right, int[] result) { int left1 = left; int right1 = mid; int left2 = mid + 1; int right2 = right; int k = 0; //先把较小的数移入到临时数组 while (left1 <= right1 && left2 <= right2) { if (nums[left1] <= nums[left2]) { result[k++] = nums[left1++]; } else { result[k++] = nums[left2++]; } } //把左边剩余的数移入 while (left1 <= right1) { result[k++] = nums[left1++]; } //把右边剩余的数移入 while (left2 <= right2) { result[k++] = nums[left2++]; } //将排序好的覆盖到nums数组 for (int i = 0; i < k; i++) { nums[left + i] = result[i]; } }}
归并排序的空间复杂度是O(n),因为其用到了一个大小为n的辅助数组来保存合并排序。
在这里我们分析一下快速排序的空间复杂度:首先快排使用的空间是O(1)的,但其递归调用会消耗空间,因为递归栈(全局)的深度是O(logn)。所以其最优的空间复杂度为O(logn)。最差的情况下空间复杂度为:O(n):退化为冒泡排序的情况。
从空间复杂度来看:堆排序最好O(1),其次是快速排序O(logn),最后是归并排序O(n)。
从稳定性来看:应选归并排序,因为快速排序和堆排序都是不稳定的。
堆排序,快排,归并排序的时间复杂度都是O(nlong)。快排最坏情况下是O(n^2)--退化为冒泡的时候。
综合来看,选快速排序。
- 归并排序算法原理及JAVA实现
- 归并排序原理及Java实现
- 归并排序原理及Java实现
- 归并排序原理及实现
- 【排序算法】归并排序原理及Java实现
- 【排序算法】归并排序原理及Java实现
- 归并排序算法的原理及JAVA实现
- 归并排序算法的原理及JAVA实现
- 归并排序算法的原理及JAVA实现
- 算法分析(二)归并排序原理及java实现
- 归并排序及Java实现
- java归并排序及实现
- 归并排序及java实现
- 归并排序原理及代码实现
- 归并排序 原理及其java实现
- 归并排序 原理和java实现
- 归并排序原理(java实现)
- 归并排序Java实现及错误总结
- Java排序算法(转)
- Android消息提醒
- 目标
- Eclise常用快捷键
- codeforces 766 A Mahmoud and Longest Uncommon Subsequence
- 归并排序原理及Java实现
- 事件驱动的HLog写入模型
- {小结}GDKOI2017 被翻盘记
- PHP+ffmpeg+nginx的配置实现视频转码
- 性能测试工具原理与架构
- 1022.Digital Library (30)...to be continued...
- spring cloud学习(六)Spring Cloud Config
- SVG
- 《机器学习》周志华 读书笔记(原创)