分治-最大子数组(算法导论P39)

版权声明:本文为博主原创文章,转载请注明出处,并附有原文链接。 https://blog.csdn.net/lady_killer9/article/details/85526930

题目:给定一个整数数组,找出和最大得到子数组,返回其和。例如,(1,-2,3,5,-1,2)最大子数组(3,5,-1,2),和为9.
分析:利用分治思想,将数组分为两段,则,最大子数组在左子数组、右子数组、或者跨在两个子数组中间。
      对于左右子数组利用递归解决,跨在中间的左右扩展即可。

      MaxSubArr(int A[], int from, int to)参数:数组A,起始位置from,结束位置to。时间复杂度:O(nlogn)

函数代码:

//查找最大子数组函数 
int MaxSubArr(int A[], int from, int to)
{
	if (from == to)
		return A[from];//递归出口
	else
	{
		int mid = 0;
		mid = (from + to) / 2;
		int max_left, max_mid, max_right;
		max_left = MaxSubArr(A, from, mid);//递归查找左子数组的最大子数组 
		max_right = MaxSubArr(A, mid + 1, to);//递归查找右子数组的最大之数组 
		//查找跨中间值的最大子数组 
		int i, left = A[mid];int now = A[mid];//从A[mid]向左扩展
		for (i = mid - 1;i >= from;i--)
		{
			now += A[i];
			left = max(now, left); //比较找出向左扩展最大值 
		}
		int right = A[mid + 1];now = A[mid + 1];//从A[mid+1]向右扩展 
		for (i = mid + 2;i <= to;i++)
		{
			now += A[i];
			right = max(now, right); //比较找出向右扩展最大值 
		}
		max_mid = left + right;
		return max(max(max_left, max_mid), max_right);
	}
}

全部代码:

/*
Project: MaxSubArr
Date:    2018/12/31
Author:  Frank Yu
题目:给定一个整数数组,找出和最大得到子数组,返回其和。例如,(1,-2,3,5,-1,2)最大子数组(3,5,-1,2),和为9.
分析:利用分治思想,将数组分为两段,则,最大子数组在左子数组、右子数组、或者跨在两个子数组中间。
      对于左右子数组利用递归解决,跨在中间的左右扩展即可。
	  MaxSubArr(int A[], int from, int to)参数:数组A,起始位置from,结束位置to。时间复杂度:O(nlogn)
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define MaxSize 100
#define Status int
using namespace std;
int n = 0;
int A[MaxSize];
//***************************基本操作函数*******************************//
//初始化数组函数,构造一个空的数组 
Status InitArray(int A[])
{
	memset(A, 0, sizeof(A));//初始化数据为0
	return 0;
}
//创建数组函数 初始化前n个数据
bool CreatArray(int A[], int &n)
{
	if (n<0 || n>MaxSize)false;//n非法
	for (int i = 0;i<n;i++)
	{
		scanf("%d", &A[i]);
	}
	return true;
}
//查找最大子数组函数 
int MaxSubArr(int A[], int from, int to)
{
	if (from == to)
		return A[from];//递归出口
	else
	{
		int mid = 0;
		mid = (from + to) / 2;
		int max_left, max_mid, max_right;
		max_left = MaxSubArr(A, from, mid);//递归查找左子数组的最大子数组 
		max_right = MaxSubArr(A, mid + 1, to);//递归查找右子数组的最大之数组 
		//查找跨中间值的最大子数组 
		int i, left = A[mid];int now = A[mid];//从A[mid]向左扩展
		for (i = mid - 1;i >= from;i--)
		{
			now += A[i];
			left = max(now, left); //比较找出向左扩展最大值 
		}
		int right = A[mid + 1];now = A[mid + 1];//从A[mid+1]向右扩展 
		for (i = mid + 2;i <= to;i++)
		{
			now += A[i];
			right = max(now, right); //比较找出向右扩展最大值 
		}
		max_mid = left + right;
		return max(max(max_left, max_mid), max_right);
	}
}
//********************************功能函数*****************************************//
//输出功能函数 按位置从小到大输出数组所有元素
void PrintArray(int A[], int &n)
{
	printf("当前数组所有元素:");
	for (int i = 0;i<n;i++)
	{
		printf("%d ", A[i]);
	}
	printf("\n");
}
//创建数组函数
void Create(int A[], int &n)
{
	bool flag;
	printf("请输入要创建的数组长度(>1):");
	scanf("%d", &n);
	printf("请输入%d个数(空格隔开):", n);
	flag = CreatArray(A, n);
	if (flag) {
		printf("创建成功!\n");
		PrintArray(A, n);
	}
	else printf("输入长度非法!\n");

}
//寻找最大子数组 
void Find_MaxSubArr(int A[], int n)
{
	int max;
	if (0 == n) printf("最大子数组为:0\n");
	else
	{
		max = MaxSubArr(A, 0, n - 1);
		printf("最大子数组为:%d\n", max);
	}
}
//菜单
void menu()
{
	printf("********1.创建    2.返回最大子数组*********\n");
	printf("********3.退出\n");
}

int main()
{
	int choice;
	InitArray(A);
	while (1)
	{
		menu();
		printf("请输入菜单序号:\n");
		scanf("%d", &choice);
		if (3 == choice) break;
		switch (choice)
		{
		case 1:Create(A, n);break;
		case 2:Find_MaxSubArr(A, n);break;
		default:printf("输入错误!!!\n");
		}
	}
	return 0;
}

运行截图:

运行截图

更多数据结构实现:数据结构严蔚敏版的实现(含全部代码)

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。

猜你喜欢

转载自blog.csdn.net/lady_killer9/article/details/85526930