二路归并排序

来源:互联网 发布:seo与sem的区别 编辑:程序博客网 时间:2024/06/18 11:04

        二路归并的基本思想:将初始序列的n个元素看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个长度为2的有序子序列,然后再对这n/2个有序子序列进行两两归并,得到n/4个长度为4的有序子序列,直到得到一个长度为n的有序序列。

        具体实现:现有无序序列46、25、68、33、33、19、12、80

初始状态:


第一次划分:


第二次划分:


第三次划分:


这样就把原始序列划分成n个子序列了,下面开始归并操作

第一次归并,每两组元素进行归并操作:


第二次归并:


第三次归并:


这样整个排序就完成了。归并排序中,归并操作时最关键的,对于两组有序元素(25, 46), (33, 80),从第一个元素开始找出较小的25,然后继续比较(46, 33),找出较小的33,继续比较(46, 80), 选出较小的46, 此时一组元素已经遍历完了,然后把另一组元素顺序加在后面,对于(19, 33), (12, 80)也是一样的道理。在整个归并过程中需要一个新的数组来保存原始的数据,然后进行归并操作,并把归并结果存到原来的数组中。下面看一下具体的代码实现

    public static void mergeSort(int [] l, int [] result, int left, int right){        if(left < right){            int middle = (left + right)/2;            mergeSort(l, result, left, middle);            mergeSort(l, result, middle + 1, right);            merge(l, result, left, right, middle);        }    }    public static void merge(int [] l, int [] result, int left, int right, int middle){        int p1, p2;        int i = p1 = left;        System.arraycopy(l, 0, result, 0, l.length);        p2 = middle + 1;        while (p1 <= middle && p2 <= right){            if(result[p2] >= result[p1]){                l[i] = result[p1];                p1 ++;            }            else{                l[i] = result[p2];                p2 ++;            }            i ++;        }        while (p1 <= middle){            l[i] = result[p1];            i ++;            p1 ++;        }        while (p2 <= middle){            l[i] = result[p2];            i ++;            p2 ++;        }    }
  时间复杂度:O(n * log2n)

        空间复杂度O(n);从代码中可以看出,归并操作每次从左半边开始操纵,遇到相等的元素以左半边的元素为准,所以归并排序是稳定的。


0 0