分治法 & 归并排序
2016-03-16 11:11
169 查看
分治法的思想
分治法的思想就是将原有的问题分解成几个规模较小的类似于原问题的子问题,通过递归的求解子问题,然后合并子问题的解来求取原问题的解。分治法主要包含三个步骤:
分解:将原问题分解为若干个子问题,这些子问题的规模小于原问题。
解决:递归的求解子问题。若子问题的规模足够小时,则直接求解。
合并:合并子问题的解,求解原问题。
归并排序
归并排序完全遵循分治法的思想。具体体现如下:分解:分解待排序的n个元素为n/2个元素的两个子序列。
解决:使用归并排序递归的对两个子序列排序。当子序列元素个数为1时,终止递归。
合并:合并两个已排序的子序列,完成排序过程。
归并排序的分析
为了便于分析,将归并排序的输入规模设为2的幂。归并排序一个元素时需要常量时间。当n>1时,可以按照分治法的三个步骤分解运行时间。分解:在这个步骤中只用计算数组的中间位置,需要常量时间。
解决:该步骤中需要递归的求解两个子问题,运行时间为2T(n/2)。
合并:合并一个具有n个元素的子数组需要Θ(n)的运行时间。
因此有:
T(n)=Θ(1),n=1
T(n)=2T(n/2)+Θ(n),n>1
对于n>1时,对T(n)采用树形结构对其分解如下图所示:
总时间为:T(n)=cnlgn+Θ(n)
归并排序的实现
#include <stdio.h> #include <stdlib.h> void merge(int *A, int l, int m, int r) { int *tmp, i, j, k, len; len = r - l + 1; tmp = (int *)malloc(sizeof(int) * len); if (tmp == NULL) { fprintf(stderr, "out of memory\n"); exit(1); } i = l, j = m + 1; k = 0; while (i <= m && j <= r) { if (A[i] <= A[j]) { tmp[k++] = A[i++]; } else { tmp[k++] = A[j++]; } } while (i <= m) { tmp[k++] = A[i++]; } while (j <= r) { tmp[k++] = A[j++]; } for (i = 0; i < len; i++) { A[l + i] = tmp[i]; } free(tmp); } void msort(int *A, int l, int r) { int m; if (l < r) { m = (l + r) / 2; msort(A, l, m); msort(A, m + 1, r); merge(A, l, m, r); } }
相关文章推荐
- JAVA数组
- Android文字长度未超过屏幕宽度也可以滚动的TextView
- 欢迎使用CSDN-markdown编辑器
- Oracle Net Services 配置: Error: null Oracle Net Services 配置失败。退出代码是1
- Meteor 组件 iron router 路由
- Android SDK开发 -- TitleBar重构 - 使用策略模式、舍弃代理模式
- Python中的正则表达式(re)
- 批处理 - 精简
- 如何解决 You have new mail in /var/spool/mail/root
- ajax加载外部json并显示在页面
- Linux Vim使用技巧【简】
- Java学习(一)
- IOS网络图片缓存详解
- OC-初识面向对象
- iOS开发证书"此证书的签发者无效"解决方法
- [上下界网络流判定] BZOJ 2406 矩阵
- 关于gitlab
- nyoj600
- 蓝桥杯B六-----加变乘
- DL:CNN-ImageNet Classification with Deep Convolution Neural Networks