实验4递归与分治策略的应用Word文档格式.docx

上传人:b****5 文档编号:17202587 上传时间:2022-11-28 格式:DOCX 页数:21 大小:414.73KB
下载 相关 举报
实验4递归与分治策略的应用Word文档格式.docx_第1页
第1页 / 共21页
实验4递归与分治策略的应用Word文档格式.docx_第2页
第2页 / 共21页
实验4递归与分治策略的应用Word文档格式.docx_第3页
第3页 / 共21页
实验4递归与分治策略的应用Word文档格式.docx_第4页
第4页 / 共21页
实验4递归与分治策略的应用Word文档格式.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

实验4递归与分治策略的应用Word文档格式.docx

《实验4递归与分治策略的应用Word文档格式.docx》由会员分享,可在线阅读,更多相关《实验4递归与分治策略的应用Word文档格式.docx(21页珍藏版)》请在冰豆网上搜索。

实验4递归与分治策略的应用Word文档格式.docx

运行到一定规模:

快速排序:

堆排序:

矩阵乘法:

1朴素算法:

2Strassen矩阵乘算法

一定规模后:

横坐标计算规模:

1:

81292:

655363:

1310724:

2621445:

1048576

随着输入规模的增大,通过三种算法的时间记录做成折线图观察不难发现,在初期,三种算法所用时间几乎相等,随着输入规模的不断增大,堆排序和快速排序仍然能够保持相对较小的增长,而并归排序所用时间复杂度开始大幅度增加。

快速排序果然是快,数据越大优势越明显,并且实现上也较为简单。

理论上它的平均时间和归并排序,堆排序都是一样的(在最坏情况还还不如它们),都是O(nlog2n),但实际运行来看比它们两者的速度都快一倍以上。

COOL!

合并排序需要额外相同规模的数组,空间复杂度为O(n)。

从具体实现来看,这只是一种理论上的优秀算法,想法比较简单直接,但实现上比quicksort 

复杂,运行时间也差,在数据很大的时候运行时间是heapsort的两倍,更不用说quicksort了。

堆排序利用了二分树的结构,将时间复杂度降到O(nlog2n),理论上和实现上表现都不错,并且发现在数据量是10 

000 

000时,甚至优于快排,可能是运行时数据的问题。

对于strassen算法对其时间复杂度分析:

T(n)=7T(n/2)+O(n);

而朴素算法的时间复杂度为n的三次方。

随着数据增大,也出现乘方级别的时间复杂度差距。

//头文件

#include<

iostream>

stdio.h>

windows.h>

time.h>

string.h>

#definePARENT(i)(i/2)//几个较简单函数

#defineLEFT(i)(2*i+1)

#defineRIGHT(i)(2*i+2)

usingnamespacestd;

//定义所需要变量等

#defineMAX100000

inta[MAX];

//数组存储原始顺序

inttemp[MAX];

//临时数组存储临时排序值

intnum;

//计算统计逆序对数

intN=2;

//数据规模

clock_tbegintimes,endtimes;

//clock_t为clock()函数返回的变量类型

doubleduration;

//运行时间计算

intheapsize;

//堆长度

//随机生成数函数

intnumber(){

inta;

a=rand()%10000+1;

//随机生成1到一万之间的整数

returna;

}

//初始化函数对数组a[]初始化。

voidinit(){

memset(temp,0,MAX*sizeof(int));

//临时数组清零

for(inti=0;

i<

N;

i++){//新数组赋值

a[i]=number();

}

return;

//单次并归挑选

voidMerge(intleft,intmid,intright)//需要三个参数,将原来数组分割

{

inti=left,j=mid+1,n=0,length=right-left;

//i开始为左半部分最左边,j为右半部分最左边

while(i<

=mid&

&

j<

=right){//未超限进行循环填数

if(a[i]>

a[j]){//左边比右边大

temp[n++]=a[j++];

num+=mid-i+1;

//从i到mid都比a[j]大

}

else{

temp[n++]=a[i++];

if(i>

mid){//左边全部填满了,填右边

while(j<

=right){

else{//右边填满,填左边

while(i<

=mid){

for(intk=0;

k<

=length;

k++){//最后临时数组赋值到原数组

a[left+k]=temp[k];

//递归进行并归排序

voidMergeSort(intleft,intright)

if(left<

right){

intmid=(left+right)/2;

MergeSort(left,mid);

MergeSort(mid+1,right);

Merge(left,mid,right);

//快速排序一次

intPartition(intleft,intright)

inti=left-1;

for(intj=left;

=right-1;

j++){

if(a[j]<

a[right]){//把right作为轴

i++;

//这个i坐标左边的值是比a[right]小的

swap(a[i],a[j]);

//交换

swap(a[i+1],a[right]);

//最后把i+1和right交换,这样轴就是i+1了必须是保证i+1上当初就是作为标杆的a[right]啊。

returni+1;

//递归进行快排整体

voidQuickSort(intleft,intright){

intq=Partition(left,right);

QuickSort(left,q-1);

QuickSort(q+1,right);

//堆排序,函数太多,新建一个命名空间

namespaceMySort{

template<

typenameT>

//堆排序的大顶堆优化(找数)

voidMax_Heapify(T*arr,inti,size_theapSize){

//从元素A[i]、A[LEFT(i)]、A[RIGHT(i)]中找出最大的,并将其下标保存在Largest中

//size_theapSize=sizeof(arr)/sizeof(*(arr));

也就是数量n

intl=LEFT(i);

intr=RIGHT(i);

intlargest;

//寻找

if(l<

heapSize&

*(arr+l)>

*(arr+i))

largest=l;

else

largest=i;

if(r<

*(arr+r)>

*(arr+largest))

largest=r;

if(largest!

=i){

swap(*(arr+i),*(arr+largest));

Max_Heapify(arr,largest,heapSize);

//如果A[i]是最大的,则以i为根的子树已经是最大堆

//建立大顶堆,采用上面大顶堆方法进行优化

voidBuild_Max_Heap(T*arr,size_theapSize){//从底部开始进行向上优化

for(inti=heapSize/2-1;

i>

=0;

i--)

Max_Heapify(arr,i,heapSize);

template<

//获得最大顶堆,堆排序开始,即元素出堆

voidHeapSort(T*arr,size_theapSize){

Build_Max_Heap(arr,heapSize);

for(inti=heapSize-1;

0;

i--){

swap(*arr,*(arr+i));

Max_Heapify(arr,0,i);

intmain(){

N=2;

do{

N*=2;

//依次增大计算规模

srand((unsigned)time(NULL));

//给一个时间种子

init();

//初始化一次

cout<

<

"

进行规模为"

<

N<

的排序"

endl;

原始数组为:

"

;

for(inti=0;

i++){

cout<

a[i]<

begintimes=clock();

//计时开始

MergeSort(0,N-1);

QuickSort(0,N-1);

MySort:

:

HeapSort<

int>

(a,N);

endtimes=clock();

//计时结束

duration=1000*(double)(endtimes-begintimes)/CLK_TCK;

//总共用时(毫秒)

排序后数组为:

此次用时为"

duration<

毫秒"

endl<

//记录实验结果,注意运行一次手动进行数据转移,清除数据

FILE*fpWrite1=fopen("

data1.txt"

"

a+"

);

//记录实验结果

fprintf(fpWrite1,"

%d\n"

N);

fclose(fpWrite1);

FILE*fpWrite2=fopen("

data2.txt"

fprintf(fpWrite2,"

duration);

fclose(fpWrite2);

}while(duration<

180000);

//单次时间小于3分钟

return0;

#defineMAX10000

intN;

a=rand()%100+1;

//最朴素算法三重循环

voidpusu(int**arr,int**brr,int**crr){

=N-1;

i++){

for(intj=0;

j++){

for(intk=0;

k++){

crr[i][j]+=arr[i][k]*brr[k][j];

}

//Strassen矩阵乘法算法,矩阵分块,仅仅针对2的n次幂次阶处理

voidgerResultStrassen(int**arr,int**brr,intn,int**crr){

if(n==1){

crr[0][0]+=arr[0][0]*brr[0][0];

else{

intm=n/2;

int**arr11=newint*[m];

int**arr12=newint*[m];

int**arr21=newint*[m];

int**arr22=newint*[m];

int**brr11=newint*[m];

int**brr12=newint*[m];

int**brr21=newint*[m];

int**brr22=newint*[m];

int**crr11=newint*[m];

int**crr12=newint*[m];

int**crr21=newint*[m];

int**crr22=newint*[m];

m;

++i){

arr11[i]=newint[m];

arr12[i]=newint[m];

arr21[i]=newint[m];

arr22[i]=newint[m];

brr11[i]=newint[m];

brr12[i]=newint[m];

brr21[i]=newint[m];

brr22[i]=newint[m];

crr11[i]=newint[m];

crr12[i]=newint[m];

crr21[i]=newint[m];

crr22[i]=newint[m];

}//获取矩阵

//四块矩阵的分别计算

//11

for(intj=0;

++j){

arr11[i][j]=arr[i][j];

brr11[i][j]=brr[i][j];

//22

for(inti=m;

n;

for(intj=m;

arr22[i-m][j-m]=arr[i][j];

brr22[i-m][j-m]=brr[i][j];

//12

arr12[i][j-m]=arr[i][j];

brr12[i][j-m]=brr[i][j];

//21

arr21[i-m][j]=arr[i][j];

brr21[i-m][j]=brr[i][j];

crr11[i][j]=0;

crr12[i][j]=0;

crr21[i][j]=0;

crr22[i][j]=0;

//递归分治

gerResultStrassen(arr11,brr11,m,crr11);

gerResultStrassen(arr12,brr21,m,crr11);

gerResultStrassen(arr11,brr12,m,crr12);

gerResultStrassen(arr12,brr22,m,crr12);

gerResultStrassen(arr21,brr11,m,crr21);

gerResultStrassen(arr22,brr21,m,crr21);

gerResultStrassen(arr21,brr12,m,crr22);

gerResultStrassen(arr22,brr22,m,crr22);

//一下是矩阵的分为四块

crr[i][j]+=crr11[i][j];

crr[i][j]+=crr22[i-m][j-m];

crr[i][j]+=crr12[i][j-m];

crr[i][j]+=crr12[i-m][j];

//后期处理

delete[]arr11[i];

delete[]brr11[i];

delete[]crr11[i];

delete[]arr12[i];

delete[]brr12[i];

delete[]crr12[i];

delete[]arr21[i];

delete[]brr21[i];

delete[]crr21[i];

delete[]arr22[i];

delete[]brr22[i];

delete[]crr22[i];

delete[]arr11;

delete[]brr11;

delete[]crr11;

delete[]arr12;

delete[]brr12;

delete[]crr12;

delete[]arr21;

delete[]brr21;

delete[]crr21;

delete[]arr22;

delete[]brr22;

delete[]crr22;

//初始化函数

voidinit(int**arr,int**brr,int**crr){

//初始化赋值

arr[i][j]=number();

crr[i][j]=0;

brr[i][j]=number();

//输出函数

voidinput(int**arr,int**brr,int**crr){

cout<

矩阵A\n"

++i)

{

++j)

{

arr[i][j]<

矩阵B\n"

brr[i][j]<

相乘后的矩阵C\n"

crr[i][j]<

所用时间为:

//主函数

intmain()

//矩阵的阶数

N=N*2;

int**arr=newint*[N];

//定义数组,分别存放三个矩阵

int**brr=newint*[N];

int**crr=newint*[N];

//获取矩阵

arr[i]=newint[N];

brr[i]=newint[N];

crr[i]=newint[N];

//给一个时

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

当前位置:首页 > 初中教育 > 英语

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

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