分治法
子程序直接调用自己或通过一系列条用语句间接调用自己。分治和递归经常同时应用于算法设计之中,并由此产生许多高校的算法。分解--》求解--》合并
时间复杂度:O(nlogn)
归并排序C版(偏伪代码)
#include "MergeSort.h"
#include<stdio.h>
void MergeSort(int A[],int p,int r)
{
int q;
if(p<r){
q=(p+r)/2;
MergeSort(A,p,q);
MergeSort(A,q+1,r);
Merge(A,p,q,r)
}
}
void Merge(int A[],int p,int q,int r)
{
int n1=q-p+1;//一个数组的长度p到q
int n2=r-q;//一个数组的长度从q+1到r
int i,j,k;
int L[50],R[50];
for(i=0; i<n1; i++)
{
L[i]=A[p+i];//把A数组左边放入新的数组
}
for(j=0; j<n2; j++)
{
R[j]=A[q+1+j];把A数组右边放入新的数组
}
L[n1]=INT_MAX;
R[n2]=INT_MAX;
j=0;
i=0;
for(k=p; k<r+1; k++)
{
if(L[i]<R[j])// 当前元素小于左边的当前元素则取右半边的元素
{
A[k]=L[i];
i++;
}
else
{
A[k]=R[j];
j++;
}
}
}
归并排序C版本2(偏伪)
#include "Merge.h"
#include<stdlib.h>
#define MAX 65536
void merges(int arr[],int p,int q,int r)
{
int *left,*right;
int n1,n2,i,j,k;
n1=q-p+1;
n2=r-q;
if((left=(int*)malloc((n1+1)*sizeof(int)))==NULL)
{
perror("malloc error");
exit(1);
}
if((right=(int*)malloc((n2+1)*sizeof(int)))==NULL)
{
perror("malloc error");
exit(1);
}
//复制数组
for(i=0; i<n1; i++)
{
left[i]=arr[p+1];
}
left[i]=MAX;
for(i=0; i<n2; i++)
{
right[i]=arr[q+i+1];
}
right[i]=MAX;
//归并开始
i=0;
j=0;
for(k=p; k<=r; k++) //从头到尾遍历
{
if(left[i]<right[j])
{
arr[k]=right[j];
j++;
}
else
{
arr[k]=left[i];
i++;
}
}
void mergesort(int arr[],int begin,int end)
{
int mid;
if(begin<end)
{
mid=(begin+end)/2;
mergesort(arr,begin,mid);
mergesort(arr,mid+1,end);
merges(arr,begin,end);
}
}
}
最大子段和
注意是子段肯定是连续的不能跳跃,(-2,11,-4,13,-5,-2)时,子段{11,-4,13}为最大子段,和为20。
第一种情况: 计算 left 到 center 的最大和,记作 leftSum
第二种情况: 计算从 center+1 到 right的最大和,记作 rightSum
第三种情况: 跨边界的和。以center为中心分别向两边计算和。
a.从 center出发,每次向左边扩张一步,并且记录当前的值S1,如果当前的和比上次的和大,就更新S1,一 直向左扩张到 位置 Left。
b.从 center+1出发,每次扩张一步,计算当前的和 为S2,如果当前的值比上次的和 大,那么,就更新S2的 值,一直向右扩张到位置Right。
c.计算过center的连续值的和,S1+S2的值 Sum。 这个就是跨边界的和。
上面三种情况考虑计算完成后,最后一步就是,比较三个值中的最大值,取最大值就可以了。
---参考https://www.cnblogs.com/lixing-nlp/p/7629403.html
#include<stdlib.h>
/*求解最大子段*/
int MaxSubSum(int *Array,int left,int right)
{
int sum=0;
int i;
if(left==right)//特殊情况
{
if(Array[left]>0)
{
sum=Array[left];
}
else
{
sum=0;
}
}
else
{
int center = (left+right)/2;
int leftsum=MaxSubSum(Array,left,center);
int rightsum=MaxSubSum(Array,center+1,right);
int s1=0;
int lefts=0;
for(i=center; i>=left; i--)//左边的数向左蔓延相加求和
{
lefts=lefts+Array[i];
if(lefts>s1)
{
s1=lefts;
}
}
int s2=0;
int rights=0;
for(i=center; i<=rights; i++)//右边的数向右蔓延相加求和
{
rights=rights+Array[i];
if(rights>s2)
{
s2=rights;
}
}
sum=s1+s2;//过center的值
if(sum<lefts)
{
sum=leftsum;
}
if(sum<rightsum)
{
sum=rightsum;
}
}
return sum;
}