数据结构与算法分析笔记(6)——归并排序

来源:互联网 发布:windows live 账号注册 编辑:程序博客网 时间:2024/06/06 16:31

归并排序:要将一个数组排序,可以先(递归地)将它分成两半分别排序,然后将结果归并起来。归并排序最吸引人的性质是它能够保证将任意长度为N的数组排序所需时间和NlogN成正比;它的主要缺点则是它所需的额外空间和N成正比。

基本思想:

  • 将数组一分为(Divide array into two halves)
  • 对每部分进行递归式地排序(Recursively sort each half)
  • 合并两个部分(Merge two halves)

演示:


1. 给出原数组a[],该数组的lo到mid,mid+1到hi的子数组是各自有序的

2. 将数组复制到辅助数组(auxiliary array)中,给两部分的首元素分别以i和j的下标,给原数组首元素以k的下标


3. 比较i下标和j下标的元素,将较小值赋到k下标位置的元素内,然后对k和赋值的下标进行递增;
    该演示里j下标的元素比较小,于是将A赋到k的位置里,再对k和j递增,即j+1, k+1

4. 重复上述过程,直到比较完全部元素。

public class Merge {private static int[] aux;public static void sort(int[] a){aux = new int[a.length];sort(a,0,a.length-1);}private static void sort(int[] a,int lo,int hi){if(hi <=lo) return;int mid = lo + (hi-lo)/2;sort(a,lo,mid);//将左半边排序sort(a,mid+1,hi);//将右半边排序merge(a,lo,mid,hi);//归并结果}public static void merge(int[] a,int lo,int mid,int hi){//将a[lo..mid]和a[mid+1..hi]归并int i = lo, j = mid+1;for(int k= lo;k <= hi;k++)//将a[lo..hi]复制到aux[lo..hi]aux[k] = a[k];for(int k = lo;k <= hi;k++){if (i >mid)                    a[k] = aux[j++];else if (j > hi)               a[k] = aux[i++];else if (aux[j] < aux[i])      a[k] = aux[j++];else                           a[k] = aux[i++];}}}

性能分析:

算法复杂度为N*log(N)


优化:

问题:归并排序需要根据数组大小N开辟额外的内存

 

原地算法(in-place Algorithm):占用额外空间小于等于c log(N)的排序算法。

插入排序、选择排序、希尔排序都属于原地算法。归并排序不属于原地算法。Wiki参考

Kronrod在1969年发明了原地归并排序(in-place merge),不过看起来好像不是那么有用(Challenge for the bored)


0 0
原创粉丝点击