图解归并排序

来源:互联网 发布:淘宝推广平台哪个好 编辑:程序博客网 时间:2024/06/05 02:06

归并排序的流程如下

第一步:对数列每次都进行切分,直到不能再切分
这里写图片描述

每次都对数列进行切分分组,直到每组的元素都只有一个,学过递归的话很容易想到这种重复性的动作用递归很容易实现。对于8个数的数列,切分三次直到第四层就不能再切分了。

第二步:进行归并

对于上述的数列,当每组的元素都是一个,也就是说每组的都是有序的了,递归返回,返回到倒数第二层。此时可对每组元素进行归并

这里写图片描述

再进行归并

这里写图片描述

可以看到归并将每组的数排成有序的了,最后我们将最后两组数再进行归并即可。

这里写图片描述

此时,数列有序,归并结束

编程思路

对于每次把数列按半切分分组,对分好的组进行归并这个流程可以用递归实现:

//归并过程    public static void merge(int arr[],int l,int mid,int r){        //归并排序辅助数组        int T[] = new int[r-l+1];        //T[0]到T[r-l]保存arr[l]到arr[r]的值        for(int i = l; i <= r; i++){            T[i-l] = arr[i];        }        //使用i指向分组1的第一个数的位置,j指向分组2的第一个数的索引        int i = l,j = mid+1;        //需要归并的数组位置是[l,r]        for(int k = l ; k <= r; k++){            if(i > mid){    //归并后分组2还有元素,依次覆盖到原数组对应处                arr[k] = T[j-l];                j++;            }else if(j > r){    //归并后分组2还有元素,依次覆盖到原数组对应处                arr[k] = T[i-l];                i++;            }else if(T[i-l] < T[j-l]){ //将分组中小的数覆盖到原数组对应处                arr[k] = T[i-l];                i++;            }else if(T[i-l] >= T[j-l]){                arr[k] = T[j-l];                j++;            }        }    }

T[]是辅助数组,用来存放两个需要进行归并的分组。在归并时,每次将两组中的最小的那个数依次放到原数组。

这个过程如下所示:
这里写图片描述

优化

public static void merge_sort(int arr[],int l,int r){        if(l >= r)            return;        /**对于数不是很多的情况下,可以使用插入排序代替归并来提高效率         * if(r - l <= 10){         *      插入排序;         *      return;         * }        */        int mid = (l+r) / 2;        merge_sort(arr,l,mid);        merge_sort(arr,mid+1,r);        //优化,归并时左边的最后一个数已经是小于右边第一个数时,可以不用归并了        if(arr[mid] > arr[mid+1]){            merge(arr,l,mid,r);        }    }
原创粉丝点击