您的位置:首页 > 其它

分治策略求解子数组最大和并输出下标

2014-08-01 15:58 281 查看
//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 17using 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;elsemaxSum = crossSum;}return maxSum;}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐