//FindMaxSubarray.h
//寻找最大子数组的和,分成三种情况来讨论
/*
在数组A[low...high]中,任何连续子数组A[i...j]的位置有三种
一、完全位于数组A[low...mid]中,因此low<=i<=j<=mid
二、完全位于数组A[mid+1...high]中,因此mid<i<=j<=mid
三、跨越了中点,因此low<=i<=mid<j<=high
*/
class FindMaxSubarray
{
public:
//寻找跨越中点的数组,得到的是crossLow,crossHigh,crossSum
void findMaxCrossingSubarray(int *,int,int,int);
//寻找和最大的子数组,得到的是lLow,hHigh,sSum,
void findMaxSubarray(int *,int,int);
int getLow(){return lLow;}
int getHigh(){return hHigh;}
int getSum(){return sSum;}
private:
int leftLow,leftHigh,leftSum;
int rightLow,rightHigh,rightSum;
int crossLow,crossHigh,crossSum;
int lLow,hHigh,sSum;
};
void FindMaxSubarray::findMaxCrossingSubarray(int *sPtr,int low,int mid,int high)
{
int sum=0;//临时子数组和,sum不赋值就蛋疼了!!!!!!!!!!
//mid左边的最大和
int left_sum = sPtr[mid];//最接近mid位置的数作为left_sum
for(int k=mid;k>=low;k--)
{
sum = sum + sPtr[k];
if(sum>left_sum)//寻找mid左边最大和
{
left_sum = sum;
lLow = k;
}
}
int right_sum = sPtr[mid+1];//最接近mid位置的数作为right_sum
sum = 0;
for(int k=mid+1;k<=high;k++)
{
sum = sum + sPtr[k];
if(sum>right_sum)//寻找mid右边最大和
{
right_sum = sum;
hHigh = k;
}
}
//得到跨越mid的字串最大和
sSum = left_sum + right_sum;
}
void FindMaxSubarray::findMaxSubarray(int * sPtr,int low,int high)
{
if(low == high)//只有一个元素的起情况
{
lLow = low;
hHigh = high;
sSum = sPtr[low];
}
else
{
int mid = (low+high)/2;
findMaxSubarray(sPtr,low,mid);//找出mid左边最大数组和
leftLow = lLow;
leftHigh = hHigh;
leftSum = sSum;
findMaxSubarray(sPtr,mid+1,high);//找出mid右边最大数组和
rightLow = lLow;
rightHigh = hHigh;
rightSum = sSum;
findMaxCrossingSubarray(sPtr,low,mid,high);//找出跨越mid的最大数组和
crossLow = lLow;
crossHigh = hHigh;
crossSum = sSum;
//比较leftSum,rightSum,crossSum的大小来确定sSum
if((leftSum>=rightSum)&&(leftSum>=crossSum))
{
lLow = leftLow;
hHigh = leftHigh;
sSum = leftSum;
}
else if((rightSum>=leftSum)&&(rightSum>=crossSum))
{
lLow = rightLow;
hHigh = rightHigh;
sSum = rightSum;
}
else
{
lLow = crossLow;
hHigh = crossHigh;
sSum = crossSum;
}
}
}
//findMaxSubarray.cpp
//寻找最大子数组的和
#include "FindMaxSubarray.h"
#define NUMBER 17
#include <iostream>
using namespace std;
int main()
{
int testArray[NUMBER+1] = {0,13,-3,-25,-20,-3,-16,23,18,20,-7,12,-5,-22,15,-4,7};
FindMaxSubarray f1;
f1.findMaxSubarray(testArray,1,NUMBER);
cout << "output the array :" << endl;
for(int i=1;i<=NUMBER;i++)
cout << " " << testArray[i];
cout << "\nthe max subarray index is " << f1.getLow() << " to "
<< f1.getHigh() << endl;
cout << "the array is :";
for(int i=f1.getLow();i<=f1.getHigh();i++)
cout << " " << testArray[i];
cout << "\nmax subarray is : " << f1.getSum();
system("pause >> cout");
return 0;
}
下面的是只需要求出子数组最大和,不要求输出下标的程序
<pre name="code" class="cpp">#include <iostream>
#define NUMBER 17
using namespace std;
int findMaxCrossingSubarray(int *,int,int,int);//跨越mid的最大数组和
int findMaxSubarray(int *,int,int);
int main()
{
int testArray[NUMBER] = {0,13,-3,-25,-20,-3,-16,23,18,20,-7,12,-5,-22,15,-4,7};
cout << "output the array :";
for(int i=1;i<NUMBER;i++)
cout << " " << testArray[i];
cout << "\nthe max subarray sum is :"
<< findMaxSubarray(testArray,1,NUMBER-1);
system("pause >> cout");
return 0;
}
int findMaxCrossingSubarray(int *sPtr,int low,int mid,int high)
{
int sum=0;
int left_sum = sPtr[mid];
for(int i=mid;i>=low;i--)
{
sum = sum + sPtr[i];
if(sum>left_sum)
left_sum = sum;
}
int right_sum = sPtr[mid+1];
sum = 0;
for(int k=mid+1;k<=high;k++)
{
sum = sum + sPtr[k];
if(sum>right_sum)
right_sum = sum;
}
sum = left_sum + right_sum;
return sum;
}
int findMaxSubarray(int *sPtr,int low,int high)
{
int maxSum;
if(low == high)
maxSum = sPtr[low];
else
{
int mid = (low+high)/2;
int leftSum = findMaxSubarray(sPtr,low,mid);
int crossSum = findMaxCrossingSubarray(sPtr,low,mid,high);
int rightSum = findMaxSubarray(sPtr,mid+1,high);
if(leftSum>=rightSum && leftSum>=crossSum)
maxSum = leftSum;
else if(rightSum>=leftSum && rightSum>=crossSum)
maxSum = rightSum;
else
maxSum = crossSum;
}
return maxSum;
}