您的位置:首页 > 其它

小白学算法2.5——归并排序(自顶而下)

2015-11-27 15:34 204 查看

小白学算法2.5——归并排序(自顶而下)

标签: 小白学算法

1.归并排序算法

归并排序属于高级排序,时间复杂度为O(nlogn),空间复杂度为O(n)。归并排序的优点是其时间复杂度较低,任意数列的排序时间都和nlogn成正比;归并排序的缺点是其空间复杂度较高,为O(n)。

归并排序采用的是分治思想。分治的指的是把大事情分解为小事情;分治的指的是把分解的小事情各个击破,以达到击破大事情。假设有一种方法A能够将两个有序数组有序的合并到新的数组中。现在有一待排序的数组,我们将其一分为二,二分为四……最终会把这个数组分离成若干个只有一个元素的数组(只有一个元素的数组是有序数组)。这个时候调用方法A,先把相邻的一元素数组合并成二元素数组,再调用方法A,把相邻的二元素数组合并为四元素数组……最终就可以得到原来数组有序化以后的数组。

2.自顶而下的归并排序实现

归并的英文是merge,也是合并的意思,但是感觉翻译成归并更合适。归并归并,递归分解再合并,所以递归分解至少需要两个函数来实现,一个用来递归分解,一个用来合并。

如果用C语言来实现的话,要么用全局变量来开辟消耗的空间,要么在递归的函数里面开辟消耗的空间,然后把开辟数组的首元素也作为函数的参数传递给合并函数,不过这么写起来麻烦,为了逻辑上更清楚一些,笔者将使用C++类来实现归并排序。

#include "stdafx.h"
#include <STDIO.H>

class MergeSort
{
public:
void sort(int* a, int n);//用户调用排序

private:
void mergeSort(int* a, int lo, int hi);//递归
void merge(int* a, int lo, int mid, int hi);//合并

int* aux;//辅助数组
};

void MergeSort::sort(int* a, int n)
{
aux = new int
;
mergeSort(a, 0, n-1);
}

void MergeSort::mergeSort(int* a,int lo, int hi)
{
if (hi <= lo) return;
int mid = lo + (hi-lo)/2;
mergeSort(a, lo, mid);//左边有序化
mergeSort(a, mid+1, hi);//右边有序化

merge(a, lo, mid, hi);//合并
}

void MergeSort::merge(int* a, int lo, int mid, int hi)
{
int i = lo, j = mid+1;
for (int k =lo; k<=hi; k++)
aux[k] = a[k];

for (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++];
}
}

int main(int argc, char* argv[])
{
// 测试数组
int num[10]= {12,54,23,67,86,45,97,32,14,65};
int i;
// 排序之前
printf("Before sorting:\n");
for (i=0; i<10; i++)
printf("%3d",num[i]);
printf("\n");
// 进行归并排序
MergeSort test;
test.sort(num, 10);
printf("After sorting:\n");
// 排序之后
for (i=0; i<10; i++)
printf("%3d",num[i]);
printf("\n");
return 0;
}


有几个
new
就有
delete
,以免内存泄露,这方面还是Java好啊

递归函数要好好理解

以最后一次合并讲解一下
merge
的流程(也就是上面的方法A):



3.归并排序时间复杂度说明



假设N个数进行排序,分离的过程可以画成一个二叉树,这棵树一共有n层,则有2n=N,n=logN

对于0~n-1之间的任意值k,自顶向下的第k层一共有2k个数组,每个数组有2n−k个元素,每个数组归并最多需要2n−k次比较,则每层需要进行2k×2n−k=2n次比较

n层就需要n×2n次比较,即NlogN次比较,这就是归并排序的时间复杂度

4.总结

归并排序是高级排序,时间复杂度为O(nlogn),可广泛使用

归并排序的空间复杂度为O(n),这是限制其应用的最主要条件

归并排序是稳定排序

使用插入排序处理小规模的子数组(比如长度小于15的数组),可以显著提高归并排序的速度(10%~15%)

没有任何基于比较的排序算法能够保证使用少于log(N!)~NlogN次比较将长度为N的数组排序

上一条说明归并排序是一种渐进最优的基于比较的排序算法

一般来说,归并排序比希尔排序略快,运行时间的差距在常数级别之内。但是在理论上并不能证明,只能证明平均情况下希尔排序时间的增长率大于归并排序时间的增长率
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: