排序算法Java实现——归并排序

时间:2022-12-22 23:29:45

归并排序(也可以叫合并排序),其实归并排序的本质就是合并排序。

它是与插入排序、交换排序、选择排序不同的一类排序方法,不同之处在于:

它要求:待排序序列是由若干个有序子序列组成。

那么究竟什么是归并排序呢?归并这个词到底是什么意思?

首先可以理解为就是合并,然后就是这个词的由来,可以说归并这个词是个生造词。 “归并”由merge翻译而来,所以归并排序亦可以翻译为:”合并排序“。因为此算法的关键就在于合并。


一、基本思想

归并排序是将两个或两个以上的有序序列合并成一个新的有序序列本篇文章介绍的就是归并排序主要是将两个有序数据序列合并成一个新的有序序列。

合并的方法是比较各子序列的第一个记录的键值,最小的一个就是排序的第一个记录的键值。取出这个记录,继续比较各子序列现有的第一个记录的键值,便可以找出排序后的第二个键值。然后开始递归,最终得到排序结果。

所以归并排序的基础就是合并

1)有序序列的合并

归并排序的核心是:两个有序子序列的合并。

此算法的执行时间为:O(n-h+1)。

这里就不上C++代码了。

2)二路归并排序

二路归并排序是将两个有序表合并成一个有序表的排序方法。

二路归并排序是稳定的。


归并排序算法的时间复杂度为O(nlog2n)


二、代码


C++代码很简单

...

JAVA代码挺复杂的

如下:

/*@(#)MergeSort.java   2017-4-25 
 * Copy Right 2017 Bank of Communications Co.Ltd.
 * All Copyright Reserved
 */

package com.sort.cn;

/**
 * TODO Document MergeSort
 * <p>
 * @version 1.0.0,2017-4-25
 * @author Singit
 * @since 1.0.0
 */
public class MergeSort {
	static int number=0;
    public static void main(String[] args) {
        int[] a = {24, 5, 98, 28, 99, 56, 34, 2 };
        printArray("排序前:",a);
        MergeSort(a);
        printArray("排序后:",a);
    }

    private static void printArray(String pre,int[] a) {
        System.out.print(pre+"\n");
        for(int i=0;i<a.length;i++)
            System.out.print(a[i]+"\t");    
        System.out.println();
    }

    private static void MergeSort(int[] a) {
        // TODO Auto-generated method stub
        System.out.println("开始排序");
        Sort(a, 0, a.length - 1);
    }

    private static void Sort(int[] a, int left, int right) {
        if(left>=right)
            return;
    
        int mid = (left + right) / 2;
        //二路归并排序里面有两个Sort,多路归并排序里面写多个Sort就可以了
        Sort(a, left, mid);
        Sort(a, mid + 1, right);
        merge(a, left, mid, right);

    }


    private static void merge(int[] a, int left, int mid, int right) {
    
        int[] tmp = new int[a.length];
        int r1 = mid + 1;
        int tIndex = left;
        int cIndex=left;
        // 逐个归并
        while(left <=mid && r1 <= right) {
            if (a[left] <= a[r1]) 
                tmp[tIndex++] = a[left++];
            else
                tmp[tIndex++] = a[r1++];
        }
            // 将左边剩余的归并
            while (left <=mid) {
                tmp[tIndex++] = a[left++];
            }
            // 将右边剩余的归并
            while ( r1 <= right ) {
                tmp[tIndex++] = a[r1++];
            }
            
            
           
            
            System.out.println("第"+(++number)+"趟排序:\t");
            // TODO Auto-generated method stub
            //从临时数组拷贝到原数组
             while(cIndex<=right){
                    a[cIndex]=tmp[cIndex];
                    //输出中间归并排序结果
                    System.out.print(a[cIndex]+"\t");
                    cIndex++;
                }
             System.out.println();
        }
}


输出结果:

排序前:
24	5	98	28	99	56	34	2	
开始排序
第1趟排序:	
5	24	
第2趟排序:	
28	98	
第3趟排序:	
5	24	28	98	
第4趟排序:	
56	99	
第5趟排序:	
2	34	
第6趟排序:	
2	34	56	99	
第7趟排序:	
2	5	24	28	34	56	98	99	
排序后:
2	5	24	28	34	56	98	99	

三、总结

从以上代码可以看出,归并排序算法需要递归的进行分解、合并,每进行一次归并排序需要调用一次merge()方法,每次执行merge()方法需要比较n次,

SO,

归并排序算法的时间复杂度为O(nlog2n)。

归并排序的空间效率较差。因为它需要一个与原始序列同样大小的辅助序列。

归并排序是稳定的。