码迷,mamicode.com
首页 > 编程语言 > 详细

《数据结构与算法分析 C语言描述》读书笔记——分治算法

时间:2016-07-21 22:00:23      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

书中用求解最大子序列和的方式介绍了分治算法(divide-and-conquer) 
分治算法是一种相对快速的算法 运行时间为O(logN)

最大子序列和的问题如下: 
给出一组整数 A1  A2 … AN 
jk=i Ak 
若所有整数均为负 则最大子序列和为0 
e.g. 输入-2, 11,-4, 13, -5, -2 输出20(A2A4)

分治算法就如同字面描述的一样 先分再治 
分 指的是将问题分为两部分几乎相同的子问题 进行递归求解 
治 指的是将 分 的解通过简单的手段合并 得到最终解

对于上述例子 可以把数列分成两个部分: 
-2, 11, -4(后文称为Left部分) 和 13, -5, -2(后文称为Right部分) 
这样最大子序列的和的出现就有3种情况(在程序中需要分别求的)

  • 全部出现在Left部分中
  • 全部出现在Right部分中
  • 一部分在Left部分中 另一部分在Right部分中

对于第三种特殊情况 可以求包含Left部分最后一个元素和Right部分第一个元素的子序列和 这样Left部分和Right部分就链接到了一起

接下来解决递归问题

  1. 为了处理递归输入 函数需要接收左右边界的位置 那么第一次调用函数时传入的左右边界就是0和N-1了
  2. 最重要的是基本情况:当左右边界相同时 返回这个重叠位置的元素(当然前提是大于零的时候)

    大体就是这样 
    上代码

#include <stdio.h>

int imax (int a, int b, int c)
{
    return (a>b?a:b)>c?(a>b?a:b):c;
}

static int MaxSubSum(const int A[], int Left, int Right)
{
    if (Left == Right)
    {
        if (A[Left] > 0)
            return A[Left];
        else
            return 0;
    }

    int Center = (Left + Right) / 2;
    int MaxLeftSum = MaxSubSum(A, Left, Center);              //1
    int MaxRightSum = MaxSubSum(A, Center+1, Right);          //2

    int MaxLeftBorderSum = 0, LeftBorderSum = 0;              //3
    for (int i = Center; i >= Left; i--)
    {
        LeftBorderSum += A[i];
        if (LeftBorderSum > MaxLeftBorderSum)
            MaxLeftBorderSum = LeftBorderSum;
    }

    int MaxRightBorderSum = 0, RightBorderSum = 0;
    for (int i = Center+1; i <= Right; i++)
    {
        RightBorderSum += A[i];
        if (RightBorderSum > MaxRightBorderSum)
            MaxRightBorderSum = RightBorderSum;
    }                                                         //4

    return imax(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);
}

int MaxSubSequenceSum(const int A[], int N)
{
    return MaxSubSum(A, 0, N - 1);
}

int main()
{
    int A[] = {-2, 11, -4, 13, -5, -2};
    printf("%d\n", MaxSubSequenceSum(A, sizeof(A)/sizeof(A[0])));

    return 0;
}

 

1是求全部出现在Left部分中的情况 
2是求全部出现在Right部分中的情况 
3~4就是求第三种情况 
最后再比较一下找到最大值

书上说 
程序短并不意味着程序好

这个程序的优点就是 快

我的CSDN: http://blog.csdn.net/oblivion1221

《数据结构与算法分析 C语言描述》读书笔记——分治算法

标签:

原文地址:http://www.cnblogs.com/oblivion1221/p/5692987.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!