# 模式识别-查找向量中元素之和最大的连续子向量

Dennis Ritchie的主页：http://cm.bell-labs.com/who/dmr/index.html

“他出生，他工作，他走了。” ——海德格尔

10.9.他走了，在此缅怀一下，感谢他做出的杰出贡献。

/*ocular version --直白方法*/
lowbound←0
highbound←0
maxval←x[0]
for i←0 to n-1
do for j←i to n-1
do sum←x[i]
for k←i+1 to j
do sum←sum+x[k]   /*sum←x[i..j]*/
temp←max(maxval,sum)
if temp≠maxval
then lowbound←i
highbound←j
maxval←temp


/*ocular-version's variant*/
lowbound←0
highbound←0
maxval←x[0]
for i←0 to n-1
do sum←x[i]
for j←i+1 to n-1
do  sum←sum+x[j]
temp←max(maxval,sum)
if temp≠maxval
then lowbound←i
highbound←j
maxval←temp


/*recursive version*/
Type maxsum(l,h)    /*Function name, be used to recursion*/
if l=h         /*the boundary of recursive function*/
then return x[l]
ptr=(l+h)/2
lmax←x[ptr]
sum←0
for i←ptr downto l
do sum←sum+x[i]
lmax←max(lmax,sum)
rmax←x[ptr+1]
sum←0
for i←ptr+1 to h
do sum←sum+x[i]
rmax←max(rmax,sum)
return MaxInThrElem(lmax+rmax,maxsum(l,ptr),maxsum(ptr+1,h))
//----------------------------------------------------------------------------
Type MaxInThrElem(a,b,c)
temp←max(a,b)
return max(temp,c)


/*linear version*/
maxval←currval←x[0]
lowbound←highbound←0
tmplowbound←0 /*record current vector's lower boundary, if maxval update, update lowbound*/
for i←1 to n-1
do temp←currval+x[i]
if temp>x[i]  /*indicate that the current vector shouldn't be update*/
then currval←temp
else currval←x[i]     /*restart a current vector*/
tmplowbound←i
if maxval<currval    /*maxval is updated by current vector's sum, update the boundary*/
then maxval←currval
highbound←i  /*once maxval update,just use the label i to update highbound*/
if lowbound≠tmplowbound   /*jump from previous vector to current vector*/
then lowbound←tmplowbound


#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctime>
#include <cstdlib>
#include <Windows.h>
using std::cout;
using std::ios;
using std::vector;
using std::string;
using std::endl;

#define TIMES					40
#define LOW						-50
#define HIGH					50
typedef int type;
typedef enum{Fdirectcomp,Fdirectcompvari,
Frecursivecomp,Flinearcomp} FuncName;
private:
vector<type> vec;
type maxval;
size_t lowbound,highbound;
vector<size_t> rtime,numofelem;
vector< vector<size_t> > comb;

#define mintomillsec	(60*1000)
#define sectomillsec	1000
void showerr(string str);
type directcomp(const vector<type>::iterator iter,\
vector<type>::size_type length,\
size_t *lowbound,size_t *highbound);  /*方法一*/
type directcompvari(const vector<type>::iterator iter,\
vector<type>::size_type length,\
size_t *lowbound,size_t *highbound);  /*方法二*/
type recursivecomp(const vector<type>::iterator iter,\
size_t lowbound,size_t highbound);  /*方法三*/
inline type MaxInThrElem(type a, type b, type c);
type linearcomp(const vector<type>::iterator iter,\
vector<type>::size_type length,\
size_t *lowbound,size_t *highbound);  /*方法四*/
/*go on to wrap the above function*/
void CallWhichProc(FuncName fn,size_t size);
public:
/*constructor function to initialize the var*/
void GetMaxValAndBound(type *max,size_t *low,size_t *high);
vector<type>::iterator GetVecIter() {return vec.begin();}
void Generand(size_t numofrandom,type low,type high);
size_t GetFuncRunTime(FuncName fn,size_t size);
void WriteMatFile(string str);  /*provide file name*/
void test();
void appendtime(size_t time) {rtime.push_back(time);}
void appendelem(size_t elem) {numofelem.push_back(elem);}
void cleartime() {rtime.clear();}
void clearelem() {numofelem.clear();}
void clearcomb() {comb.clear();}
void combina2vec()
{
comb.push_back(numofelem);
comb.push_back(rtime);
}

int main(int argc,char *argv[])
{
size_t NUMOFRAND=1000000,STEP=0;
string fstr;
size_t rtime=0;
csd.Generand(NUMOFRAND,LOW,HIGH);
// csd.test();  //test every function's NUMOFRAND & STEP

for(size_t i=0; i != sizeof(FuncName); ++i)
{
/*every function handle different scale,because time
*every function wastes is different.we have to compromise
*between time & performance,& I just want to get the result.
*/
switch(i)
{
/*Elegant design,isn't it?*/
case 0:
NUMOFRAND=50;  /*func 1 start from 50*/
STEP=10;
fstr="F:\\Fdirectcomp.m";
break;
case 1:
NUMOFRAND=300;
STEP=50;
fstr="F:\\Fdirectcompvari.m";
break;
case 2:
NUMOFRAND=3000;
STEP=500;
fstr="F:\\Frecursivecomp.m";
break;
case 3:
NUMOFRAND=25000;
STEP=5000;
fstr="F:\\Flinearcomp.m";
break;
default:
break;
}
for(size_t j=0; j != TIMES; ++j)
{
rtime=csd.GetFuncRunTime(
static_cast<FuncName>(i),NUMOFRAND);
csd.appendelem(NUMOFRAND);
csd.appendtime(rtime);
NUMOFRAND += STEP;
cout<<"Number of Element: "<<NUMOFRAND
<<"\t\tUse Time(millisec): "<<rtime<<endl;
}
cout<<endl;
csd.combina2vec();
csd.WriteMatFile(fstr);
csd.clearelem();
csd.cleartime();
csd.clearcomb();
}
system("pause");
return 0;
}

{
}

{
Generand(1000000,LOW,HIGH);
size_t rtime,j=50;
for(size_t i=0; i != sizeof(FuncName); ++i)
{
for(; j != 1000000; ++j)
{
rtime=GetFuncRunTime(static_cast<FuncName>(i),j);
if(rtime > 100) break;
}
cout<<"scale of element:\t"<<j<<endl;
}
}

{
std::ofstream fout;
fout.open(str,ios::trunc | ios::out);
std::streambuf *outbuf=cout.rdbuf(fout.rdbuf() );
//start write to .m file
cout<<"%clear the var in current working space;"<<endl;
cout<<"clear;\nclc;"<<endl;
for(size_t i=0; i != comb.size(); ++i)
{
switch(i)
{
case 0:
cout<<"numofelem=[..."<<endl;
break;
case 1:
cout<<"rtime=[..."<<endl;
break;
default:
showerr("beyond the range of vector");
}
for(size_t j=0; j != comb[i].size(); ++j)
{
cout<<comb[i][j]<<'\t';
if((j+1) % 10 == 0) cout<<"...\n";
}
cout<<"];\n"<<endl;
}
cout<<"plot(numofelem,rtime,'+');"<<endl;
cout<<"legend('实验数据');"<<endl;
//end write to .m file
cout.rdbuf(outbuf);
fout.close();
}

{
if(max != NULL) *max=maxval;
if(low != NULL) *low=lowbound;
if(high != NULL) *high=highbound;
}

{
SYSTEMTIME tm;
DWORD s_millsec,e_millsec=s_millsec=0;
GetLocalTime(&tm);
s_millsec=tm.wMinute*mintomillsec+tm.wSecond*sectomillsec+\
tm.wMilliseconds;
/*There're so many functions,so we should enlarge the scale of
*the object need to be handled to reduce the ratio of the time
*that 'switch' expression consumes because I ! just haven't found
*the unify interface... - -! This is a kind of just so-so design.
*/
CallWhichProc(fn,size);
GetLocalTime(&tm);
e_millsec=tm.wMinute*mintomillsec+tm.wSecond*sectomillsec+\
tm.wMilliseconds;
return (e_millsec-s_millsec);
}

void CSchemaDist::Generand(size_t numofrandom, type low, type high)
{
if(numofrandom <=0)
showerr("the numbers of random you want to generate must larger than 0");
if(low>high)
showerr("the lower random must less than higher random");
type dist=high-low;
srand(static_cast<unsigned>( time(NULL) ));
for(size_t i=0; i != numofrandom; ++i)
vec.push_back(static_cast<type>( rand()%dist+low ));
}

{
switch(fn)
{
case Fdirectcomp:
maxval=directcomp(vec.begin(),size,&lowbound,&highbound);
break;
case Fdirectcompvari:
maxval=directcompvari(vec.begin(),size,&lowbound,&highbound);
break;
case Frecursivecomp:
maxval=recursivecomp(vec.begin(),0,static_cast<size_t>(size-1) );
break;
case Flinearcomp:
maxval=linearcomp(vec.begin(),size,&lowbound,&highbound);
break;
default:
break;
}
}

vector<type>::size_type length,\
size_t *lowbound,size_t *highbound)
{
type maxval=*iter,sum,temp=sum=0;

if(length <= 0)  /*robust interface,isn't it ^^*/
showerr("Length of Vector must larger than 0");

for(vector<type>::size_type i=0;i != length; ++i)
{
for(vector<type>::size_type j=i;j!=length; ++j)
{
sum=iter[i];
for(vector<type>::size_type k=i+1;k<=j ; ++k)
sum += *(iter+k);
temp=max(maxval,sum);
if(temp > maxval)
{
maxval=temp;
/*caller not always provide the parameter */
if(lowbound != NULL) *lowbound=static_cast<size_t>(i);
if(highbound != NULL) *highbound=static_cast<size_t>(j);
}
}
}
return maxval;
}

vector<type>::size_type length,\
size_t *lowbound,size_t *highbound)
{
type maxval(*iter);
type sum,temp=sum=0;

if(length <= 0)
showerr("Length of Vector must larger than 0");

for(vector<type>::size_type i=0; i != length; ++i)
{
sum = 0;
for(vector<type>::size_type j=i; j != length; ++j)
{
sum += *(iter+j);
temp = max(maxval,sum);
if(temp > maxval)
{
maxval=temp;
if(lowbound != NULL) *lowbound=static_cast<size_t>(i);
if(highbound != NULL) *highbound=static_cast<size_t>(j);
}
}
}
return maxval;
}

size_t lowbound,size_t highbound)
{
/*first call this function,you must detect if lowbound >highbound,
*but the function is recursive ,the behavior is waste so much resouce.
*so we can create a wrapper function to detect first time.
*/
size_t ptr(lowbound);
type lmax,rmax,sum=lmax=rmax=0;

if(lowbound == highbound)
return iter[lowbound];
ptr=(lowbound+highbound)/2;
sum=lmax=iter[ptr];
for(int i=ptr-1;i >=static_cast<int>(lowbound); --i)
sum += iter[i], lmax=max(lmax,sum);
sum=rmax=iter[ptr+1];
for(size_t i=ptr+2;i<=highbound; ++i)
sum += iter[i], rmax=max(rmax,sum);
return MaxInThrElem(lmax+rmax,recursivecomp(iter,lowbound,ptr),\
recursivecomp

(iter,ptr+1,highbound));
}

vector<type>::size_type length,\
size_t *lowbound,size_t *highbound)
{
if(length<=0)
showerr("Length of Vector must larger than 0");
type temp,maxval,currval=maxval=temp=iter[0];
size_t tmplowbound=0;    /*record current vector's lower boundary*/
size_t low,high=low=0;

for(vector<type>::size_type i=1; i != length; ++i)
{
temp=currval+iter[i];
if(temp > iter[i])  /*current vector shouldn't be update*/
currval=temp;
else
{
currval=iter[i];  /*restart a current vector*/
tmplowbound=static_cast<size_t>(i);
}
if(maxval < currval)  /*maxval is updated by current vector's sum*/
{
maxval=currval,high=i;
if(low != tmplowbound) low=tmplowbound;
}
}
if(lowbound != NULL) *lowbound = low;
if(highbound != NULL) *highbound = high;
return maxval;
}

inline type CSchemaDist::MaxInThrElem(type a, type b, type c)
{
type temp=max(a,b);
return max(temp,c);
}

{
cout<<str<<endl;
system("pause");
exit(0);
}

%clear the var in current working space;
clear;
clc;
numofelem=[...
50    60    70    80    90    100    110    120    130    140    ...
150    160    170    180    190    200    210    220    230    240    ...
250    260    270    280    290    300    310    320    330    340    ...
350    360    370    380    390    400    410    420    430    440    ...
];

rtime=[...
31    62    125    157    219    297    390    531    641    797    ...
1000    1203    1437    1704    2000    2344    2734    3141    3531    4031    ...
4578    5156    5907    6468    7219    7828    8688    9515    10391    11375    ...
12468    13485    14657    15875    17140    18500    19922    21422    23032    24609    ...
];

plot(numofelem,rtime,'+');
legend('实验数据');


（图一：方法一执行所得图示）

（图二：方法二执行所得图示）

（图三：方法三执行所得图示）

（图四：方法四执行所得图示）

• 评论

• 下一篇
• 上一篇