小白学算法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的数组排序
上一条说明归并排序是一种渐进最优的基于比较的排序算法
一般来说,归并排序比希尔排序略快,运行时间的差距在常数级别之内。但是在理论上并不能证明,只能证明平均情况下希尔排序时间的增长率大于归并排序时间的增长率
相关文章推荐
- tomcat结合nginx使用小结
- Android点击EditText文本框之外任何地方隐藏键盘的解决办法
- 学习ROS笔记之TF——learning tf(一)
- 关掉该死的DEP(数据执行保护,仅针对win7)
- C语言开发总结(十)
- thinkphp中的AJAX返回ajaxReturn()
- C++中随机函数rand()和srand()的用法
- AMD规范中的define和require
- Android开发总结笔记 Fragment(上) 1-2-11
- vs2010开发linux平台C程序 开发环境配置
- 如何在Eclipse开发环境进行android应用调试
- 源码一:Android部分基础控件使用总结
- pyspider 爬豆瓣电影信息
- (转载新浪博客)社保缴费为何这么多?
- C/C++文件打开方式对文本内容的显示没有影响
- Maven介绍,包括作用、核心概念、用法、常用命令、扩展及配置
- .net 类型转换汇总
- nodejs 改变全局前缀
- 4. 导航
- jquery实现的个性网站首页 详细信息