算法导论笔记——最大子数组C语言实现

第四章

分治策略


在分治策略中我们将递归的求解一个问题,在每层递归中有如下三个步骤。
分解 将问题划分为一些子问题,子问题形式与原问题一样,只是规模更小。
解决 递归的求解出子问题。如果子问题规模足够小,则停止递归,直接求
解。
合并 将子问题的解合并为原问题的解。
需要递归求解时,我们称之为 递归情况,当子问题足够小时,不需要递归时,
我们称之为递归已经 触底,进入基本情况。
递归式
一个递归式就是一个不等式或等式,通过更小的输入来描述一个函数。
三种求解递归式的方法

代入法 猜测一个界,并用数学归纳法证明。
递归树法 将递归式转换为一棵树,其节点表示不同层次的递归调用后产生的
代价。然后采用边界技术来求解递归式。
主方法 T(n) = aT(n/b)+f(n)

最大子数组问题
分治策略求解方法

分析 

可以将数组分为两个子数组,那么最大子数组一定在前一个子数组中或后一个子数组中
或经过两子数组中间。
可以递归的求解各子数组最大子数组,最后合并问题得出原问题最大子数组。


原书伪代码(查找经过前后子数组的最大子数组 即中间情况)
FIND-MAX-CROSSING-SUBARRY(A,low,mid,high)
left-sum = -∞    //左子数组最大子数组之和
sum = 0
for i = mid downto low  //查找经过中间项的最大左子数组
    sum = sum + A[i]
    if sum > left-sum
       left-sum = sum
       max-left = i
right-sum = -∞   //右子数组最大子数组之和
sum = 0
for j = mid + 1 to high  //查找经过中间项的最大右子数组
    sum = sum + A[j]
    if sum > right-sum
       right-sum = sum
       max-right = j
return(max-left,max-right,left-sum + right-sum) //合并即为最大中间子数组

C语言实现(例 查找一个10项数组的最大子数组)

#include<stdio.h>
#include<stdlib.h>
typedef struct{
int leftmax1;
int rightmax1;
int maxsum1;
}mystruct; //定义结构体用来存储最大子数组

mystruct midmax(int a[],int low,int mid,int high) //结构体函数传递每层递归最大中间子数组
{
mystruct midside;   //最大中间子数组
int sum,i,j;
int leftmax,rightmax,maxsum,max = 0;
sum = 0;
maxsum = -100;
for(i = mid;i >=low;i--) //查找经过中间项最大左子数组 
{
sum = sum+a[i];
if(sum > maxsum)
{
maxsum = sum;
leftmax = i;

}
}
max = max+maxsum; 
sum = 0;
maxsum = -100;
for(j = mid+1;j<=high;j++) //查找经过中间项最大右子数组
{
sum = sum+a[j];
if(sum>maxsum)
{
maxsum = sum;
rightmax = j;
}
}
max = max+maxsum;    //确定最大中间子数组
midside.leftmax1 = leftmax;
midside.rightmax1 = rightmax;
midside.maxsum1 = max;

return midside;
}

mystruct digui(int a[],int low,int high)
//递归部分
{
mystruct answer;
mystruct leftside;
mystruct rightside,midside;
int mid = 0;
if(low == high) //触底情况,即基本情况,直接给出答案
{
answer.leftmax1 = low;
answer.rightmax1 = high;
answer.maxsum1 = a[low];
return answer;
}
else{
mid = (low+high)/2;

leftside = digui(a,low,mid);
rightside = digui(a,mid+1,high);
midside = midmax(a,low,mid,high);
if(leftside.maxsum1 >= rightside.maxsum1&&leftside.maxsum1 >= midside.maxsum1)
return leftside;
else if(rightside.maxsum1 >= leftside.maxsum1&&rightside.maxsum1 >= midside.maxsum1)
return rightside;
else if(midside.maxsum1 >= rightside.maxsum1&&midside.maxsum1 >= leftside.maxsum1)
return midside;
} //比较每层左最大子数组,右最大子数组,中间最大子数组,确定该层最大子数组
}

int main()
{
mystruct answer;
int a[10];
a[0] = 7;
a[1] = 5;
a[2] = -4;
a[3] = 0;
a[4] = -3;
a[6] = 1;
a[7] = -2;
a[8] = 3;
a[9] = 3;
answer = digui(a,0,9); //调用函数
printf("\n %d\n",answer.maxsum1);
return 0;
}


猜你喜欢

转载自blog.csdn.net/jazrynwong/article/details/79715353