排序算法004-归并排序


一、什么是归并排序?(稳定、O(nlogn)



归并排序 (merge sort) 是一类与插入排序、交换排序、选择排序不同的另一种排序方法。归并的含义是将两个或两个以上的有序表合并成一个新的有序表。

1、一趟归并需要将数组 a[]中相邻的长度为h的有序序列进行两两归并.并将结果放到temp[]中,这需要将待排序列中的所有记录扫描一遍,因此耗费O(n),而又完全二叉树的深度可知,整个归并排序需要进行(log2n)次,因此总的时间复杂度为O(nlogn),而且这是归并排序算法中最好、最坏、平均的时间性能。 

2、对代码进行仔细研究,发现merge函数中有if (a[i] < a[j]) 的语句,说明它需要两两比较,不存在跳跃,因此归并排序是一种稳定的排序算法。 
也就是说,归并排序是一种比较占内存,但却效率高且稳定的算法。



二、两路归并排序步骤


分而治之(divide - conquer);每个递归过程涉及三个步骤
1、 分解: 把待排序的 n 个元素的序列分解成两个子序列, 每个子序列包括 n/2 个元素.
2、 治理: 对每个子序列分别调用归并排序MergeSort, 进行递归操作
3、 合并: 合并两个排好序的子序列,生成排序结果.


三、算法思想


1、此算法的实现不像图示那样简单,现分三步来讨论。首先从宏观上分析,首先让子表表长 L=1 进行处理;不断地使 L=2*L ,进行子表处理,直到 L>=n 为止,把这一过程写成一个主体框架函数 mergesort 。

2、然后对于某确定的子表表长 L ,将 n 个记录分成若干组子表,两两归并,这里显然要循环若干次,把这一步写成一个函数 mergepass ,可由 mergesort 调用。

3、最后再看每一组(一对)子表的归并,其原理是相同的,只是子表表长不同,换句话说,是子表的首记录号与尾记录号不同,把这个归并操作作为核心算法写成函数 merge ,由 mergepass 来调用。


总的来说思想就是:假设我们有一个没有排好序的序列,那么首先我们使用分割的办法将这个序列分割成一个一个已经排好序的子序列,然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。

happysneaker.com

动图排序演示如下:

happysneaker.com


四、代码实现

public class MergeSort {    
    public static void merge(int[] a, int low, int mid, int high) {
     
        int[] temp = new int[high - low + 1];        
        int i = low;// 左指针
        int j = mid + 1;// 右指针
        int k = 0;        
        
        // 把较小的数先移到新数组中
        while (i <= mid && j <= high) {            
            if (a[i] < a[j]) {
                temp[k++] = a[i++];
            } else {
                temp[k++] = a[j++];
            }
        }        
            
        // 把左边剩余的数移入数组
        while (i <= mid) {
            temp[k++] = a[i++];
        }        
        // 把右边边剩余的数移入数组
        while (j <= high) {
            temp[k++] = a[j++];
        }        
        // 把新数组中的数覆盖nums数组
        for (int k2 = 0; k2 < temp.length; k2++) {
            a[k2 + low] = temp[k2];
        }
    }    
        
    public static void mergeSort(int[] a, int low, int high) {        
        int mid = (low + high) / 2;        
        if (low < high) {            
            // 左边
            mergeSort(a, low, mid);            
            // 右边
            mergeSort(a, mid + 1, high);            
            // 左右归并
            merge(a, low, mid, high);
            System.out.println(Arrays.toString(a));
        }

    }    
    
    // 主函数
    public static void main(String[] args) {        
        int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };
        mergeSort(a, 0, a.length - 1);
        System.out.println("排序结果:" + Arrays.toString(a));
    }
}

运行结果:

happysneaker.com

Unity那些事儿
请先登录后发表评论
  • 最新评论
  • 总共0条评论