分析归并排序

来源:互联网 发布:c语言qsort函数 编辑:程序博客网 时间:2024/06/02 00:59

对于归并排序而言,我们应该需要关注一下思想,归并也是一种分治的思想,类似与快速排序,但是又和快速排序有本质的区别。

这里写图片描述

归并排序


归并排序将要排序的序列分成两个长度相等的子序列,然后对每一个子序列进行拆分,一直到只有两个元素的两个子序列,对这两个子序列进行归并,将它们合并成一个序列,这种方法就是所说的二路归并的方法。

实现归并排序的思路:
这里写图片描述

所以,综合下来,我们实现代码:

//递归解决归并排序template<typename T>void MergeSort1(T* arr, int n){    T* tmp = new T[n];    assert(tmp);    for (int i = 0; i < n; i++)    {        tmp[i] = arr[i];    }    merge_sort1(arr, tmp, 0, n - 1);}template<typename T>void merge_sort1(T* arr, T* tmp, int begin, int end){    assert(arr);    assert(tmp);    if (begin == end)        return;    int mid = begin + ((end - begin) >> 1);    int begin1 = begin;    int end1 = mid;    int begin2 = mid + 1;    int end2 = end;    //递归过程      merge_sort1(arr, tmp, begin1, end1);    merge_sort1(arr, tmp, begin2, end2);    int t = begin;    //进行两个区间归并    while (begin1 <= end1&&begin2 <= end2)    {        if (arr[begin1] > arr[begin2])        {            tmp[t++] = arr[begin2++];        }        else        {            tmp[t++] = arr[begin1++];        }    }    //如果归并完后,有剩余    while (begin1 <= end1)    {        tmp[t++] = arr[begin1++];    }    while (begin2 <= end2)    {        tmp[t++] = arr[begin2++];    }    //转到原来的空间上    for (int i = 0; i <= end; i++)    {        arr[i] = tmp[i];    }}

其实归并排序也可以进行优化的,1.利用插入排序优化归并排序
在归并中利用插入排序不仅可以减少递归次数,还可以减少内存分配次数(针对于原始版本)。

尽管合并排序最坏情况运行时间为o(nlgn),插入排序的最坏运行时间为o(n^2),但是插入排序的常数因子使得它在n较小时,运行要更快一些。因此,在合并排序算法中,当子问题足够小时,采用插入排序就比较合适了。

所以我们可以改为

template<typename T>void MergeSort1(T* arr, int n){    T* tmp = new T[n];    assert(tmp);    for (int i = 0; i < n; i++)    {        tmp[i] = arr[i];    }    if (n>5)        merge_sort1(arr, tmp, 0, n - 1);    else        InsertSort(arr, n);}

优化以后的归并排序的时间复杂度:O(nlogn)

0 0