#include <stdio.h>
#define MAGIC -999999
/* 子数组结构体 */
struct sub_array{
int low;
int high;
int sum; // 子数组的和
};
struct sub_array find_max_crossing_subarray(int a[], int low, int mid, int high);
struct sub_array find_maximum_subarray(int a[], int low, int high);
int main(void)
{
int array[16] = {13, -3, -25, 20,
-3, -16, -23, 18,
20, -7, 12, -5,
-22, 15, -4, 7};
/* 最大连续子数组 */
struct sub_array max = find_maximum_subarray(array, 0, 15);
printf("最大子数组为:\n");
for (int i = max.low; i <= max.high; i++)
{
printf("%d\n", array[i]);
}
/* 最大连续子数组的和 */
int sum = 0;
int max = -(1 << 31);
int cur = 0;
while (cur < 16)
{
sum += array[cur++];
if (sum > max)
{
max = sum;
}
else if (sum < 0)
{
sum = 0;
}
}
printf("%d\n", max);
return 0;
}
struct sub_array find_max_crossing_subarray(int a[], int low, int mid, int high)
{
struct sub_array res;
int i, j, max_left, max_right, sum;
int left_sum, right_sum;
sum = 0;
left_sum = right_sum = MAGIC;
for (i = mid; i >= 0; i--)
{
sum += a[i];
if (sum > left_sum)
{
left_sum = sum;
max_left = i;
}
}
sum = 0;
for (j = mid + 1; j < high; j++)
{
sum += a[j];
if (sum > right_sum)
{
right_sum = sum;
max_right = j;
}
}
res.low = max_left;
res.high = max_right;
res.sum = left_sum + right_sum;
return res;
}
/* 最大连续子数组要么是数组的左半部分a[0 ~ mid - 1],要么是数组的右半部分a[mid ~ n],要么是左半一部分加右半一部分a[0 ~ n] */
struct sub_array find_maximum_subarray(int a[], int low, int high)
{
struct sub_array res;
if (high == low)
{
res.low = res.high = low;
res.sum = a[low];
return res;
}
else
{
int mid = (low + high) / 2;
struct sub_array left;
struct sub_array right;
struct sub_array cross;
left = find_maximum_subarray(a, low, mid);
right = find_maximum_subarray(a, mid+1, high);
cross = find_max_crossing_subarray(a, low, mid, high);
if (left.sum >= right.sum && left.sum >= cross.sum)
{
return left;
}
else if (right.sum >= left.sum && right.sum >= cross.sum)
{
return right;
}
else
{
return cross;
}
}
}
分治法:寻找最大子数组
最新推荐文章于 2021-02-09 21:18:30 发布