归并排序算法(Java实现)

向右看齐 2022-06-06 01:38 338阅读 0赞

1、基本思想

归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。

归并排序的时间复杂度是O(N*lgN)。

2、工作原理

归并排序(Merge Sort)就是利用归并思想对数列进行排序。根据具体的实现,归并排序包括”从上往下”和”从下往上”2种方式。

下面的图片很清晰的反映了”从下往上”和”从上往下”的归并排序的区别。

这里写图片描述

从下往上的归并排序:将待排序的数列分成若干个长度为1的子数列,然后将这些数列两两合并,得到若干个长度为2的有序数列,再将这些数列两两合并,得到若干个长度为4的有序数列,再将它们两两合并,直接合并成一个数列为止。这样就得到了我们想要的排序结果。

这里写图片描述

从上往下的归并排序:它与”从下往上”在排序上是反方向的。它基本包括3步:

  1. 分解:将当前区间一分为二,即求分裂点 mid = (low + high)/2;
  2. 求解:递归地对两个子区间a[low…mid] 和 a[mid+1…high]进行归并排序。递归的终结条件是子区间长度为1。
  3. 合并:将已排序的两个子区间a[low…mid]和 a[mid+1…high]归并为一个有序的区间a[low…high]。

这里写图片描述

3、Java实现

  1. /** * @Comment 归并排序算法 * @Author Ron * @Date 2017年10月26日 下午2:56:33 * @return */
  2. public class MergeSort {
  3. /** * @Comment 合并子序列 * @Author Ron * @Date 2017年10月26日 下午5:08:11 * @param sources 待排序的数组 * @param start 第一个子序列起始位置 * @param mid 第一个子序列结束位置,第二个子序列起始位置 * @param end 第二个子序列结束位置 * @return */
  4. static void merge(int[] sources,int start,int mid,int end){
  5. int[] temp = new int[end-start+1];//汇总两个序列的临时区域
  6. int i = start;
  7. int j = mid+1;
  8. int k=0;
  9. while (i <= mid && j <= end) {
  10. if(sources[i] <= sources[j]){
  11. temp[k++]=sources[i++];
  12. }else{
  13. temp[k++]=sources[j++];
  14. }
  15. }
  16. while (i <= mid) {
  17. temp[k++]=sources[i++];
  18. }
  19. while (j <= end) {
  20. temp[k++]=sources[j++];
  21. }
  22. //将temp赋给sources
  23. for (i = 0; i < k; i++){
  24. sources[start + i] = temp[i];
  25. }
  26. }
  27. /** * @Comment * @Author Ron * @Date 2017年10月26日 下午4:28:04 * @param sources 待排序的数组 * @param gap 子序列长度 * @return */
  28. static void mergeGroup(int[] sources,int gap){
  29. int margedLength = 0;//已归并的序列起始下标
  30. int length = sources.length;
  31. for(margedLength = 0 ; margedLength + gap*2 - 1 < length; margedLength += gap*2){
  32. //合并两个子序列
  33. merge(sources, margedLength, margedLength+gap-1, margedLength+2*gap-1);
  34. }
  35. if (margedLength + gap - 1 < length) {
  36. //合并剩下的子序列
  37. merge(sources, margedLength, margedLength+gap-1, length-1);
  38. }
  39. }
  40. /** * @Comment 归并排序(从上到下) * @Author Ron * @Date 2017年10月26日 下午3:42:12 * @return */
  41. static void mergeSortOne(int[] sources){
  42. if(sources == null){
  43. return;
  44. }
  45. //分组合并
  46. for(int gap=1; gap < sources.length; gap *= 2){
  47. mergeGroup(sources,gap);
  48. }
  49. }
  50. /** * @Comment 二分归并 * @Author Ron * @Date 2017年10月26日 下午5:58:42 * @param sources 需要排序的序列 * @param start 序列起始位置 * @param end 序列结束位置 * @return */
  51. static void mergeDivide(int[] sources,int start,int end){
  52. if(sources==null || start >= end){
  53. //子区间长度为1,返回
  54. return;
  55. }
  56. int mid = (start+end)/2;
  57. mergeDivide(sources,start,mid);
  58. mergeDivide(sources,mid+1,end);
  59. merge(sources, start, mid, end);
  60. }
  61. public static void main(String[] args) {
  62. int[] a = {
  63. 80,30,60,40,20,10,50,70,90};
  64. mergeSortOne(a);
  65. for (int i=0; i<a.length; i++){
  66. System.out.printf("%d ", a[i]);
  67. }
  68. System.out.printf("\n");
  69. int[] a2 = {
  70. 80,30,60,40,20,10,50,70,90};
  71. mergeDivide(a2,0,a2.length-1);
  72. for (int i=0; i<a2.length; i++){
  73. System.out.printf("%d ", a2[i]);
  74. }
  75. }
  76. }

发表评论

表情:
评论列表 (有 0 条评论,338人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JAVA_算法_归并排序

    思想: 把一个大的数组细分成两个不同的数组, 循环这个过程。直到数组中的元素只有1或0个元素。 当数组中的只有两个元素时,比较两个元素的大小,前一个大于后一个就交换。 然

    相关 归并排序算法Java实现

    1、基本思想 归并排序(Merge)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列

    相关 归并排序算法——java

    什么是归并排序算法? 答:归并排序算法就是利用分治思想将数组分成两个小组A,B,再将A,B小组各自分成两个小组,依次类推,直到分出来的小组只有一个数据时,可以认为这个小组已经

    相关 排序算法归并排序Java实现

    归并排序的思想是将局部有序的数组合并为一个大的有序数组,前提是需要保证局部数组有序,如果局部没有顺序,那么就拆分,再合并,最差的情况是,拆到两个数组都只有一个元素的时候,这时候