分治法性能分析张富生.docx

上传人:b****5 文档编号:8306469 上传时间:2023-01-30 格式:DOCX 页数:13 大小:93.94KB
下载 相关 举报
分治法性能分析张富生.docx_第1页
第1页 / 共13页
分治法性能分析张富生.docx_第2页
第2页 / 共13页
分治法性能分析张富生.docx_第3页
第3页 / 共13页
分治法性能分析张富生.docx_第4页
第4页 / 共13页
分治法性能分析张富生.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

分治法性能分析张富生.docx

《分治法性能分析张富生.docx》由会员分享,可在线阅读,更多相关《分治法性能分析张富生.docx(13页珍藏版)》请在冰豆网上搜索。

分治法性能分析张富生.docx

分治法性能分析张富生

计算机与信息学院2015-2016-2课程论文

《最优化方法及其应用》

课程类型:

学科基础学位课

学号:

2015110406003

姓名:

张富生

专业:

软件工程

授课教师:

田卫新

 

完成日期:

2016 年7月11日

引言:

任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。

问题的规模越小,越容易直接求解,解题所需的计算时间也越少。

分治法是计算机科学中经常使用的一种算法。

设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

但是不是所有问题都适合用分治法解决。

当求解一个输入规模为n且取值又相当大的问题时,使用蛮力策略效率一般得不到保证。

因此分治策略将问题划分成k个子问题分别求解合并能有效提高计算效率。

1算法性能比较

1.1问题分析

比较插入排序,合并排序和快速排序性能。

算法性能比较通常是从时间复杂度的角度进行的。

排序算法的复杂度主要和算法中的比较次数和元素交换或移动次数有关。

因而在不同大小规模的问题中通过统计这两者之和来评判算法的优劣。

同时也可以证明各种算法的时间复杂度与问题规模n之间的关系。

1.2源程序代码

//maintest.cppfortest

#include

#include

usingnamespacestd;

//全局标记比较次数和移动次数

intcount_compare=0;

intcount_move=0;

intcount_all(){

returncount_compare+count_move;

}

voidclear_count()

{

count_compare=0;

count_move=0;

}

//insertsort

voidinsert_element(inta[],intsize,intelement)//sizebeforeinsertion

{

inti=0;

for(i=size-1;i>=0;i--)

{

count_compare++;

if(element

elsebreak;

}

a[i+1]=element;

count_move++;

}

voidInsertSort(inta[],intsize)

{

for(inti=1;i

{

insert_element(a,i,a[i]);

}

}

//mergesort

voidMerge(intc[],intd[],intl,intm,intr)

{

inti=l,j=m+1,k=l;

while(i<=m&&j<=r)

{

count_compare++;

if(c[i]<=c[j]){

d[k++]=c[i++];

count_move++;

}

else{d[k++]=c[j++];count_move++;}

}

count_compare++;

if(i>m)

{

for(intq=j;q<=r;q++){

d[k++]=c[q];

count_move++;

}

}

else

for(intq=i;q<=m;q++){

d[k++]=c[q];

count_move++;

}

}

voidCopy(inta[],intb[],intl,intr)

{

for(inti=l;i<=r;i++){

a[i]=b[i];

count_move++;

}

}

voidMergeSort(inta[],intleft,intright,intsize)

{

if(left

{

count_compare++;

inti=(right+left)/2;

intp=size;//thisisimportant,mindthevalue!

int*b=newint[p];

MergeSort(a,left,i,size);

MergeSort(a,i+1,right,size);

Merge(a,b,left,i,right);

Copy(a,b,left,right);

}

}

//quicksort

voidswap(inta[],inti,intj)

{

inttemp=a[i];

a[i]=a[j];

a[j]=temp;

count_move+=3;

}

intpartition(inta[],intp,intr)

{

inti=p,j=r+1;

intx=a[p];

while(true)

{

while(a[++i]

while(a[--j]>x)count_compare++;

count_compare++;

if(i>=j)break;

swap(a,i,j);

}

a[p]=a[j];

a[j]=x;

count_move++;

returnj;

}

voidQuickSort(inta[],intp,intr)

{

if(p

{

intq=partition(a,p,r);

QuickSort(a,p,q-1);

QuickSort(a,q+1,r);

}

count_compare++;

}

//show

voidshow_array(inta[],intsize)//显示一个数组的所有元素

{

for(inti=0;i

{

cout<

}

cout<

}

//randomarray

voidRandomArray(inta[],intsize)//随机生成数组含n个元素,其元素各不相同

{

srand(time(NULL));

for(inti=0;i

for(inti=1;i<=size;i++)

{

intp=rand()%size;

while(a[p]!

=0){p=(++p)%size;}

a[p]=i;

}

show_array(a,size);

}

//copyarray

voidCopyArray(inta[],intb[],intsize)

{

for(inti=0;i

}

intmain()

{

int*a;int*temp_a;

intsize=4;

cin>>size;

a=newint[size];

temp_a=newint[size];

RandomArray(temp_a,size);

CopyArray(temp_a,a,size);

show_array(a,size);

InsertSort(a,size);

show_array(a,size);

cout<<"插入排序比较次数为"<

cout<<"插入排序移动次数为"<

cout<<"总规模为"<

clear_count();

CopyArray(temp_a,a,size);

show_array(a,size);

MergeSort(a,0,size-1,size);

show_array(a,size);

cout<<"合并排序比较次数为"<

cout<<"合并排序移动次数为"<

cout<<"总规模为"<

clear_count();

CopyArray(temp_a,a,size);

show_array(a,size);

QuickSort(a,0,size-1);

show_array(a,size);

cout<<"快速排序比较次数为"<

cout<<"快速排序移动次数为"<

cout<<"总规模为"<

show_array(a,size);

system("pause");

return0;

}}

1.3运行示例

1.4数据分析

(单次录入数据具有较大随机误差,只看增长趋势)

问题规模(n)

排序总复杂度规模(T(n))

插入排序

合并排序

快速排序

10

57

105

50

20

221

280

122

30

367

461

238

40

946

660

371

50

1394

879

432

80

3261

1570

856

100

4694

2064

1064

200

22912

4718

2447

500

130133

13668

7368

1000

504254

30309

17003

10000

43898103

401968

225489

根据列表分析,插入算法平均复杂度为,合并算法平均复杂度为,快速排序算法平均复杂度为,但是排序算法最坏情况下复杂度仍为,为了验证这一点,取n=1000的已排好数组,快排总规模变为503497,取n=10000的已排好数组,快排总规模变为50034997。

说明快排算法对已经基本排好的数组反而耗时间更多。

2循环赛问题

2.1问题描述

设有n个运动员要进行网球循环赛。

设计一个满足下列条件的比赛日程表:

每个选手必须与其他n-1个选手各赛一次;

每个选手一天只能赛一次;

当n是偶数时,循环赛进行n-1天。

当n是奇数时,循环赛进行n天。

2.2问题分析

当n=(k=1、2、3、4,……,n=2、4、8、16,……)时,此时问题比较简单。

按照分治的策略,可将所有参赛的选手分为两部分,n=个选手的比赛日程表就可以通过为n/2=个选手设计的比赛日程表来决定。

递归地执行这种分割,直到只剩下2个选手时,比赛日程表的制定就变得很简单:

只要让这2个选手进行比赛就可以了。

再逐步合并子问题的解即可得到原问题的解。

推广当n为任意整数时:

当n小于或等于1时,没有比赛。

当n是偶数时,至少举行n-1轮比赛.

当n是奇数时,至少举行n轮比赛,这时每轮将会有一支球队轮空。

因此应对策略如下:

(1)当n/2为偶数时,与n=情形类似,可用分治法求解。

(2)当n/2为奇数时,递归返回的轮空的比赛要作进一步处理。

可以在前n/2轮比赛中让轮空选手与下一个未参赛选手进行比赛。

2.3源程序

#include

usingnamespacestd;

inta[100][100];

intb[100];

boolodd(intn)//判断n奇偶性

{

returnn&1;//n为奇数,返回1,n为偶数,返回0

}

voidcopyodd(intn)//n/2为奇数时的合并算法

{

intm=n/2;

for(inti=0;i

{

b[i]=m+i;

b[m+i]=b[i];

}

for(inti=0;i

{

//由左上角小块的值算出相应的左下角小块的值

for(intj=0;j

{

if(a[i][j]>=m)

{

a[i][j]=b[i];

a[m+i][j]=(b[i]+m)%n;

}

elsea[m+i][j]=a[i][j]+m;

}

//由左上角小块的值算出相应的右上角和右下角小块的值

for(intj=1;j

{

a[i][m+j]=b[i+j];

a[b[i+j]][m+j]=i;

}

}

}

voidcopy(intn)

{

intm=n/2;

for(inti=0;i

for(intj=0;j

{

//由左上角小块的值算出对应的右上角小块的值

a[i][j+m]=a[i][j]+m;

//由右上角小块的值算出对应的左下角小块的值

a[i+m][j]=a[i][j+m];

//由左上角小块的值算出对应的右下角小块的值

a[i+m][j+m]=a[i][j];

}

}

voidmakecopy(intn)//合并算法

{

if((n/2)>1&&odd(n/2))copyodd(n);//n/2为奇数时

elsecopy(n);

}

voidtourna(intn)//改进的分治赛算法

{

if(n==1){a[0][0]=0;return;}

if(odd(n)){tourna(n+1);return;}//n为奇数,分治

tourna(n/2);//n为偶数,分治

makecopy(n);//合并

}

intmain()

{

intn;

cout<<"请输入参数队数:

"<

cin>>n;

tourna(n);

cout<<"参数日程表为:

"<

for(inti=0;i

for(intj=0;j

cout<

cout<

}

system("pause");

return0;

}

2.4运行示例

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1