基础算法系列(五)——归并排序
2012-11-15 00:53
211 查看
和快排相同,归并排序时间复杂度也是O(nlogn),同时它还是一种稳定排序。本文以二路归并为例,而实际应用常采用多路归并进行外部排序,这一点笔者后续会补充。
算法思想:
运用了分治理念,通常是将待排序数组从中间一分为二,再对这两段分别进行归并排序,最后将排序后的两段合并(故称二路归并),合并时通常需要一个与数组长度相等的额外空间保存临时结果。如果不用这个额外空间也可以完成排序,只是那样算法效率会受到影响。
代码实例:
复杂度分析:
以上面代码为例,可知归并过程总是先将数组分解为单个元素,再两两合并而成,分解的过程类似一颗二叉树,总共进行了nlogn次比较操作,时间复杂度O(nlogn),空间复杂度O(n)
重要特性:
1、稳定排序
2、无论原始数据如何排列,都能保证O(nlogn)的时间复杂度
算法思想:
运用了分治理念,通常是将待排序数组从中间一分为二,再对这两段分别进行归并排序,最后将排序后的两段合并(故称二路归并),合并时通常需要一个与数组长度相等的额外空间保存临时结果。如果不用这个额外空间也可以完成排序,只是那样算法效率会受到影响。
代码实例:
void _merge(int array[], int len_a, int len_b, int tmp[]) { int i, j, k; for(i = 0, j = len_a, k = 0; k < len_a + len_b; k++) { if(i == len_a) { tmp[k] = array[j++]; continue; } if(j == len_a + len_b) { tmp[k] = array[i++]; continue; } tmp[k] = (array[i] <= array[j]) ? array[i++] : array[j++]; } for(i = 0; i < len_a + len_b; i++) { // 将排序后的拷贝回去 array[i] = tmp[i]; } } void _merge_sort(int array[], int left, int right, int tmp[]) { if(left < right) { int mid = left + ((right - left)>>1); // (left + right)/2相加时可能溢出 _merge_sort(array, left, mid, tmp); _merge_sort(array, mid + 1, right, tmp); _merge(array + left, mid - left + 1, right - mid, tmp); // 合并结果 } } void merge_sort(int array[], int len) { int *tmp = (int *)malloc(len*sizeof(int)); // 分配存储临时结果的空间 assert(tmp != NULL); memset(tmp, 0, len); _merge_sort(array, 0, len - 1, tmp); free(tmp); // 记得释放内存 }
复杂度分析:
以上面代码为例,可知归并过程总是先将数组分解为单个元素,再两两合并而成,分解的过程类似一颗二叉树,总共进行了nlogn次比较操作,时间复杂度O(nlogn),空间复杂度O(n)
重要特性:
1、稳定排序
2、无论原始数据如何排列,都能保证O(nlogn)的时间复杂度
相关文章推荐
- 算法熟记-排序系列-归并排序
- 算法基础:分治模式,归并排序ΘΘΘΘΘΘ知识小结
- 算法基础-归并排序
- 算法设计与应用基础系列1
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 B - Ignatius and the Princess IV
- [架构设计] CUDA系列学习(五)GPU基础算法: Reduce, Scan, Histogram
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 G - 免费馅饼
- Python 从基础------进阶------算法 系列
- 经典基础算法之面试题(系列一)(转)
- 图像处理基础知识系列之一:边界跟踪之内边界跟踪算法解释
- 基础算法-归并排序
- 算法设计与应用基础系列9
- 算法设计与应用基础系列11
- 算法设计与应用基础系列2
- 算法基础:排序之归并排序
- 【基础算法】- 2路归并排序
- 基础算法系列(四)——快速排序
- 算法系列之归并排序
- 零基础算法系列代码_用递归实现进制转换
- 经典基础算法之面试题(系列一)