分治算法

本文详细阐述了分治法的基本思想及其应用,包括将大问题分解为子问题、递归求解并合并结果的三个核心步骤。通过快速排序等实例说明自顶向下与自底向上的分治策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分治的简明意思是:将大问题分成一个一个小问题,进行解决。

下面说说分治法解决问题的具体三个步骤(蕴含递归思想):

1.将原问题分解为一组子问题,每个子问题都与原问题类型相同,但是比原问题的规模小。

2.递归求解这些子问题。

3.将子问题的求解结果恰当合并,得到原问题的解。

以上三条能够运用分治法完全取决于第二和第三条,若不符合可以考虑动态规划贪心法

根据分治法的分割原则,原问题应该分为多少个子问题才较适宜?各个子问题的规模应该怎样才为适当?这些问题很难予以肯定的回答。但人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之有效的。许多问题可以取k=2。这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。

分治法的两种方式:

1自顶向下:就是上面说的解决步骤

2.自底向上:如果知道了最终直接可解的原子问题的全部情况,那么可采用由原子问题出发,向上递推的方法,由已有结论的小尺寸问题的解决,导致比它高一层次的同类问题的解决,最终使原问题彻底解决.这就是和递归向下方法对应的由底向上的分治方法的基本思路.

注:这个思想的关键是 分解

比较体现分治算法的具体例子:

快速排序,它的基本思想是:选择一个基准值,进行划分(比“基准值”小的元素居左边,比“基准值”大的元素居右边,基准值居中),然后对左右两半分别进行快速排序.这种划分不断进行,直到区域元素个数为1或0.这种尺寸为0或1的排序问题就是原子问题

另一个体现自底向上的思想的代码为:

Code:
  1. unsignedcountbits(unsignedx)
  2. {
  3. staticunsignedmask[]={
  4. 0x55555555,0x33333333,
  5. 0x0F0F0F0F,0x00FF00FF,
  6. 0x0000FFFF
  7. };
  8. for(unsignedi=0,shift=1;i<5;i++,shift<<=1)
  9. {
  10. x=(x&mask[i])+((x>>shift)&mask[i]);
  11. }
  12. returnx;
  13. }

以上代码请自行理解,以便你更好的理解分治算法。

..........................................................无敌分界线.......................................................

上面算法是求一个16进制数转换成2进制后一共含有几个1.也是最难想到的!

下面我们看看下面算法:

Code:
  1. #include<stdio.h>
  2. unsignedcountbits(unsignedx)
  3. {
  4. unsignedn=0;
  5. while(x)
  6. {
  7. x=x&(x-1);//和自己的上一个数进行与运算,每次都会关掉一个1
  8. ++n;//记录
  9. }
  10. returnn;
  11. }
  12. intmain(void)
  13. {
  14. intm;
  15. while(scanf("%d",&m)!=EOF)
  16. {
  17. printf("二进制中含有的1一共有%d/n",countbits(m));
  18. }
  19. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值