分治算法求最大子数组以及其对应的下标<c/c++源代码>
2014-11-19 21:24
246 查看
参考:http://wenku.baidu.com/link?url=9f_-NmepWw2DoZaj01FHw3udtlS7Pa6fSI-mie-yU1BE8ZLjxgduVPj7B2u-Rfwfbn9eiHuPcp1ggiIccAcN9aLyWmLd3uOux7HbIMc92NG
求解连续子数组的最大值,基本和参考文献一样,本文只是记录了连续子数组的上下界,原文记录上下界方式有误!
更改主要在如下三点:
1、最大值出现在单点上或者连续的几点上,所以在递归算法的收敛位置记录下标值且更新最大值为当前最大值
2、单点出现在分治算法的叶子节点即FIND_MAXIMUM_SUBARRAY的收敛点,连续点出现在分治算法树的父节点即FIND_MAX_CROSSING_SUBARRAY的最值点
3、对于1、2都必须同时更新最大值和最大连续子数组的上下界
#include <iostream>
using namespace std;
#define INF -1000 //定义一个很小的值代表于负无穷
int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high);
int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high);
int pos_low,pos_high,val; //定义全局变量存放起始位置以及满足FIND_MAX_CROSSING_SUBARRAY的和最大值
int max_sum = INF;//
//分治法排序
int main()
{
int A[]={-1,-2,45,-3,1};
int *a = A;
cout<<*(a)<<endl;
int LEN_A=sizeof(A)/sizeof(int);
cout<<"maxArrayValues is : "<<FIND_MAXIMUM_SUBARRAY(A,1,LEN_A)<<endl;
cout<<pos_low<<" "<<pos_high<<" "<<val<<" "<<max_sum<<endl;
cout<<A[pos_low]<<" "<<A[pos_high]<<endl;
return 0;
}
//跨中点最大子数组的处理方式,分治方法的核心思想。
//分别计算左右两边的最大子数组,在合并中必被包含在里面。
int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high)
{
int L_sum, R_sum, sum;
int max_L, max_R;
//左边
L_sum = INF; sum = 0;
for (int i = mid-1;i >= low-1; i--)
{
sum+=*(q+i);
if (sum > L_sum)//关键部分
{
L_sum=sum;//存值,记录位置
max_L=i;
}
}
//右边
R_sum=INF;sum=0;
for (int j=mid;j<high;j++)
{
sum+=*(q+j);
if(sum>R_sum)
{
R_sum=sum;
max_R=j;
}
}
val=L_sum+R_sum;//存储结果
if(val>max_sum)
{
cout<<"1>>>>>>>"<<endl;
pos_low=max_L,pos_high=max_R;
max_sum = val;
}
return (max_L,max_R,L_sum+R_sum);//返回值表达式为逗号表示式,只返回最后一个量,这一点不完美,所以用全局变量存储
}
//递归程序
int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high)
{
int mid;
int data[3];//存放左中右三种情况下的最大子数组的和值
if (high == low)
{
//每次递归都从单个值开始递归计算,可能在单个点上出现最大值
if(*(p+low-1)>max_sum)
{
//保存叶子节点的最大值
max_sum = *(p+low-1);
pos_low = low-1;
pos_high = low-1;
}
return (low,high,*(p+low-1));
}
else
{
mid=(low+high)/2;
data[0]=FIND_MAXIMUM_SUBARRAY(p,low,mid);//从形参中可以看出范围,分别代表左中右
data[1]=FIND_MAXIMUM_SUBARRAY(p,mid+1,high);
data[2]=FIND_MAX_CROSSING_SUBARRAY(p,low,mid,high);
if ((data[0]>=data[1])&&(data[0]>=data[2]))
{
return (data[0]);
}
else if ((data[1]>=data[0])&&(data[1]>=data[2]))
{
return (data[1]);
}
else
{
return (data[2]);
}
}
}
求解连续子数组的最大值,基本和参考文献一样,本文只是记录了连续子数组的上下界,原文记录上下界方式有误!
更改主要在如下三点:
1、最大值出现在单点上或者连续的几点上,所以在递归算法的收敛位置记录下标值且更新最大值为当前最大值
2、单点出现在分治算法的叶子节点即FIND_MAXIMUM_SUBARRAY的收敛点,连续点出现在分治算法树的父节点即FIND_MAX_CROSSING_SUBARRAY的最值点
3、对于1、2都必须同时更新最大值和最大连续子数组的上下界
#include <iostream>
using namespace std;
#define INF -1000 //定义一个很小的值代表于负无穷
int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high);
int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high);
int pos_low,pos_high,val; //定义全局变量存放起始位置以及满足FIND_MAX_CROSSING_SUBARRAY的和最大值
int max_sum = INF;//
//分治法排序
int main()
{
int A[]={-1,-2,45,-3,1};
int *a = A;
cout<<*(a)<<endl;
int LEN_A=sizeof(A)/sizeof(int);
cout<<"maxArrayValues is : "<<FIND_MAXIMUM_SUBARRAY(A,1,LEN_A)<<endl;
cout<<pos_low<<" "<<pos_high<<" "<<val<<" "<<max_sum<<endl;
cout<<A[pos_low]<<" "<<A[pos_high]<<endl;
return 0;
}
//跨中点最大子数组的处理方式,分治方法的核心思想。
//分别计算左右两边的最大子数组,在合并中必被包含在里面。
int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high)
{
int L_sum, R_sum, sum;
int max_L, max_R;
//左边
L_sum = INF; sum = 0;
for (int i = mid-1;i >= low-1; i--)
{
sum+=*(q+i);
if (sum > L_sum)//关键部分
{
L_sum=sum;//存值,记录位置
max_L=i;
}
}
//右边
R_sum=INF;sum=0;
for (int j=mid;j<high;j++)
{
sum+=*(q+j);
if(sum>R_sum)
{
R_sum=sum;
max_R=j;
}
}
val=L_sum+R_sum;//存储结果
if(val>max_sum)
{
cout<<"1>>>>>>>"<<endl;
pos_low=max_L,pos_high=max_R;
max_sum = val;
}
return (max_L,max_R,L_sum+R_sum);//返回值表达式为逗号表示式,只返回最后一个量,这一点不完美,所以用全局变量存储
}
//递归程序
int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high)
{
int mid;
int data[3];//存放左中右三种情况下的最大子数组的和值
if (high == low)
{
//每次递归都从单个值开始递归计算,可能在单个点上出现最大值
if(*(p+low-1)>max_sum)
{
//保存叶子节点的最大值
max_sum = *(p+low-1);
pos_low = low-1;
pos_high = low-1;
}
return (low,high,*(p+low-1));
}
else
{
mid=(low+high)/2;
data[0]=FIND_MAXIMUM_SUBARRAY(p,low,mid);//从形参中可以看出范围,分别代表左中右
data[1]=FIND_MAXIMUM_SUBARRAY(p,mid+1,high);
data[2]=FIND_MAX_CROSSING_SUBARRAY(p,low,mid,high);
if ((data[0]>=data[1])&&(data[0]>=data[2]))
{
return (data[0]);
}
else if ((data[1]>=data[0])&&(data[1]>=data[2]))
{
return (data[1]);
}
else
{
return (data[2]);
}
}
}
相关文章推荐
- 有一个整型二维数组,假设a[3][4] = {初始化了值},求出这个二维数组中所有的最大值,以及最大值对应的下标。 数组内部原有的值不能改变位置。
- 实验 6 数组1题目1、输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标
- 10.2 设计一个函数模板 max <T>求一个数组中最大的元素,并以整数数组和字符数 组进行调用
- .NET中string[]数组和List<string>泛型的相互转换以及Array类的Sort()方法 【整理】
- 求子数组的最大和___<3>
- 【hpu oj 1127 用递归求数组中元素的最大值以及下标】
- ArrayList ,string , string[] 数组的转换 以及二维数组定义ArrayList<String[]>
- Linq学习__03__数据源是IEnumerable<T> 变量,Concat,匿名类,数组下标,返回字符串,group by,orderby
- 字符串的运算符重载(如:赋值‘=’、加'+'、加等'+='、下标'[]'相等'=='、不等'!='、大于'>'、输出运算符'<<'以及类型转换)
- 一些html的缩写对应的意义以及常用单词的意思<新手向><持续更新>
- 实验 6 数组1、输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标。
- <C/C++>指向指针的指针、指向数组的指针以及存放指针的数组
- 算法3:找出一个整数数组里面两个查值最大的两个下标a[j]-a[i]最大并且i<j
- 数组问题之一维最大字段和问题<Java实现>
- 实验6 数组1(输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标。)
- 实验 6-1输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标
- 实验 6 数组1输出最大值和它所对应的下标
- 实验6-1 输入n个整数,将它们存入数组a中。输出最大值和它所对应的下标
- Javascript中获取数组最大值和最小值以及最大值和最小值的下标 没学对象前的最简单最基本的方法
- <跟着结构之法一起学算法>求子数组的最大和