算法设计与分析报告报告材料实验二Word文件下载.docx

上传人:b****6 文档编号:19050702 上传时间:2023-01-03 格式:DOCX 页数:14 大小:25.36KB
下载 相关 举报
算法设计与分析报告报告材料实验二Word文件下载.docx_第1页
第1页 / 共14页
算法设计与分析报告报告材料实验二Word文件下载.docx_第2页
第2页 / 共14页
算法设计与分析报告报告材料实验二Word文件下载.docx_第3页
第3页 / 共14页
算法设计与分析报告报告材料实验二Word文件下载.docx_第4页
第4页 / 共14页
算法设计与分析报告报告材料实验二Word文件下载.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

算法设计与分析报告报告材料实验二Word文件下载.docx

《算法设计与分析报告报告材料实验二Word文件下载.docx》由会员分享,可在线阅读,更多相关《算法设计与分析报告报告材料实验二Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。

算法设计与分析报告报告材料实验二Word文件下载.docx

2. 

 

thenreturn(ADHOC(P))

3. 

将P分解为较小的子问题P1,P2,...,Pk

4. 

fori←1tok

5. 

doyi←Divide-and-Conquer(Pi) 

△递归解决Pi

6. 

T←MERGE(y1,y2,...,yk) 

△合并子问题

7. 

return(T)

其中|P|表示问题P的规模;

n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。

ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。

因此,当P的规模不超过n0时,直接用算法ADHOC(P)求解。

算法MERGE(y1,y2,...,yk)是该分治法中的合并子算法,用于将P的子问题P1,P2,...,Pk的相应的解y1,y2,...,yk合并为P的解。

根据分治法的分割原则,原问题应该分为多少个子问题才较适宜?

各个子问题的规模应该怎样才为适当?

这些问题很难予以肯定的回答。

但人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。

换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之有效的。

许多问题可以取k=2。

这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。

分治法的合并步骤是算法的关键所在。

有些问题的合并方法比较明显,有些问题合并方法比较复杂,或者是有多种合并方案;

或者是合并方案不明显。

究竟应该怎样合并,没有统一的模式,需要具体问题具体分析。

四、实验内容

1、编程实现归并排序算法和快速排序算法,程序中加入比较次数的计数功能,输出排序结果和比较次数。

输入10组相同的数据,验证排序结果和完成排序的比较次数。

用表格列出比较结果。

给出文字分析。

2、汉诺塔(hanoi)问题。

3、棋盘覆盖问题。

4、循环赛日程安排问题。

五、算法设计

1、归并排序算法

procedureMERGESORT(low,high)

//A(low;

high)是一个全程数组,它含

有high-low+1≥0个待排序的元素//

integerlow,high;

iflow<

high;

thenmid←,//求这个集合的分割点//

callMERGESORT(low,mid)//将一个子集合排序//

callMERGESORT(mid+1,high)//将另一个子集合排序

callMERGE(low,mid,high)//归并两个已排序的子集合//

endif

endMERGESORT

归并两个已排序的集合

procedureMERGE(low,mid,high)

//A(low:

high)是一个全程数组//

//辅助数组B(low;

high)//

integerh,i,j,k;

h←low;

i←low;

j←mid+1;

whileh≤midandj≤highdo//当两个集合都没取尽时//

ifA(h)≤A(j)thenB(i)←A(h);

h←h+1

elseB(i)←A(j);

j←j+1

i←i+1

repeat

ifh>

midthen

fork←jtohighdo//处理剩余的元素//

B(i)←A(k);

i←i+1

elsefork←htomiddo

将已归并的集合复制到A

endMERGE

2、快速排序算法

我们已经知道,在决策树计算模型下,任何一个基于比较来确定两个元素相对位置的排序算法需要Ω(nlogn)计算时间。

如果我们能设计一个需要O(n1ogn)时间的排序算法,则在渐近的意义上,这个排序算法就是最优的。

许多排序算法都是追求这个目标。

下面介绍快速排序算法,它在平均情况下需要O(nlogn)时间。

这个算法是由C.A.R.Hoare发明的。

算法的基本思想:

快速排序的基本思想是基于分治策略的。

对于输入的子序列L[p..r],如果规模足够小则直接进行排序,否则分三步处理:

分解(Divide):

将输入的序列L[p..r]划分成两个非空子序列L[p..q]和L[q+1..r],使L[p..q]中任一元素的值不大于L[q+1..r]中任一元素的值。

递归求解(Conquer):

通过递归调用快速排序算法分别对L[p..q]和L[q+1..r]进行排序。

合并(Merge):

由于对分解出的两个子序列的排序是就地进行的,所以在L[p..q]和L[q+1..r]都排好序后不需要执行任何计算L[p..r]就已排好序。

这个解决流程是符合分治法的基本步骤的。

因此,快速排序法是分治法的经典应用实例之一。

QuickSort(p,q)

//将数组A[1:

n]中的元素

A[p],A[p+1],,A[q]按不降次序排列,

并假定A[n+1]是一个确定的、且大于

A[1:

n]中所有的数。

//

intp,q;

globaln,A[1:

n];

ifp<

qthen

j=Partition(p,q+1);

//划分后j成为划分元素的位置

QuickSort(p,j-1);

QuickSort(j+1,q);

endQuickSort

procedurePARTITION(m,p)

//退出过程时,p带着划分元素所在的下标位置。

integerm,p,i;

globalA(m:

p-1)

v←A(m);

i←m//A(m)是划分元素//

loop

loopi←i+1untilA(i)≥vrepeat//i由左向右移//

loopp←p-1untilA(p)≤vrepeat//p由右向左移//

ifi<

p

thencallINTERCHANGE(A(i),A(p))//A(i)和A(p)换位//

elseexit

A(m)←A(p);

A(p)←v//划分元素在位置p//

EndPARTITION

3、汉诺塔(hanoi)问题。

设有A、B、C共3根塔座,在塔座A上堆叠n个金盘,每个盘大小不同,只允许小盘在大盘之上,最底层的盘最大,如下图所示。

现在要求将A上的盘全都移到C上,在移的过程中要遵循以下原则:

每次只能移动一个盘;

圆盘可以插在A、B和C任一个塔座上;

在任何时刻,大盘不能放在小盘的上面。

hanoi问题递归求解思想:

我们把一个规模为n的hanoi问题:

1到n号盘按照移动规则从A上借助B移到C上表示为H(A,B,C,n);

原问题划分成如下三个子问题:

(1)将1到n-1号盘按照移动规则从A上借助C移到B上H(A,C,B,n-1);

(2)将n号盘从A上直接移到C上;

(3)将1到n-1号盘按照移动规则从B上借助A移到C上H(B,A,C,n-1);

经过三个子问题求解,原问题的也即求解完成。

4、盘覆盖问题。

在一个2k×

2k个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。

在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

六、参考程序代码

1、归并排序

#include<

iostream.h>

iomanip.h>

stdlib.h>

time.h>

#defineM11

typedefintKeyType;

typedefintElemType;

structrec{

KeyTypekey;

ElemTypedata;

};

typedefrecsqlist[M];

classguibing{

public:

guibing(sqlistb)

{

for(inti=0;

i<

M;

i++)

r[i]=b[i];

}

voidoutput(sqlistr,intn)

{

for(inti=0;

n;

cout<

<

setw(4)<

r[i].key;

cout<

endl;

}

voidxuanze(sqlistb,intm,intn)

inti,j,k;

for(i=m;

n-1;

{

k=i;

for(j=i;

j<

j++)

if(b[k].key>

b[j].key)k=j;

if(k!

=i)

{

rectemp=b[k];

b[k]=b[i];

b[i]=temp;

}

}

voidmerge(intl,intm,inth,sqlistr2)

xuanze(r,l,m);

xuanze(r,m,h);

output(r,M);

k=i=l;

for(j=m;

m&

&

h;

k++)

if(r[i].key<

=r[j].key)

{

r2[k]=r[i];

i++;

}

else

r2[k]=r[j];

j++;

output(r2,M);

while(j<

h)

r2[k]=r[j];

j++;

k++;

while(i<

=m)

r2[k]=r[i];

i++;

output(r2,M);

private:

sqlistr;

};

voidmain()

cout<

"

guibingfa1运行结果:

\n"

;

sqlista,b;

inti,j=0,k=M/2,n=M;

srand(time(0));

for(i=0;

a[i].key=rand()%80;

b[i].key=0;

guibinggx(a);

排序前数组:

gx.output(a,M);

数组排序过程演示:

gx.merge(j,k,n,b);

排序后数组:

gx.output(b,M);

cin.get();

2、快速排序

#defineMAXI10

typedefrecsqlist[MAXI];

classkuaisu

{

kuaisu(sqlista,intm):

n(m)

i++)b[i]=a[i];

voidquicksort(ints,intt)

inti;

if(s<

t){

i=part(s,t);

quicksort(s,i-1);

quicksort(i+1,t);

elsereturn;

intpart(ints,intt)

inti,j;

recp;

i=s;

j=t;

p=b[s];

while(i<

j)

j&

b[j].key>

=p.key)j--;

b[i]=b[j];

b[i].key<

=p.key)i++;

b[j]=b[i];

b[i]=p;

output();

returni;

voidoutput()

b[i].key;

sqlistb;

intn;

voidmain()

cout<

kuaisu1.cpp运行结果:

sqlista1;

inti,n=MAXI,low=0,high=9;

srand(time(0));

for(i=0;

a1[i].key=rand()%80;

kuaisupx(a1,n);

px.quicksort(low,high);

px.output();

cin.get();

}

3、hanoi问题递归求解代码:

voidH(charA,charB,charC,intn)

if(n>

0)

H(A,C,B,n-1);

printf(“%dfrom%cto%c”,n,A,C);

H(B,A,C,n-1);

4、棋盘覆盖问题。

voidchessBoard(inttr,inttc,intdr,intdc,intsize)

if(size==1)return;

intt=tile++, 

//L型骨牌号

s=size/2;

//分割棋盘

//覆盖左上角子棋盘

if(dr<

tr+s&

dc<

tc+s)

//特殊方格在此棋盘中

chessBoard(tr,tc,dr,dc,s);

else{//此棋盘中无特殊方格

//用t号L型骨牌覆盖右下角

board[tr+s-1][tc+s-1]=t;

//覆盖其余方格

chessBoard(tr,tc,tr+s-1,tc+s-1,s);

//覆盖右上角子棋盘

dc>

=tc+s)

chessBoard(tr,tc+s,dr,dc,s);

//用t号L型骨牌覆盖左下角

board[tr+s-1][tc+s]=t;

chessBoard(tr,tc+s,tr+s-1,tc+s,s);

//覆盖左下角子棋盘

if(dr>

=tr+s&

chessBoard(tr+s,tc,dr,dc,s);

else{//用t号L型骨牌覆盖右上角

board[tr+s][tc+s-1]=t;

chessBoard(tr+s,tc,tr+s,tc+s-1,s);

//覆盖右下角子棋盘

chessBoard(tr+s,tc+s,dr,dc,s);

else{//用t号L型骨牌覆盖左上角

board[tr+s][tc+s]=t;

chessBoard(tr+s,tc+s,tr+s,tc+s,s);

5、循环赛日程安排问题

#include"

stdio.h"

voidTable(intk,inta[][9])

intn=1;

for(inti=1;

=k;

i++)n*=2;

for(i=1;

=n;

i++)a[1][i]=i;

intm=1;

for(ints=1;

s<

s++)

n/=2;

for(intt=1;

t<

t++)

for(i=m+1;

=2*m;

for(intj=m+1;

a[i][j+(t-1)*m*2]=a[i-m][j+(t-1)*m*2-m];

a[i][j+(t-1)*m*2-m]=a[i-m][j+(t-1)*m*2];

m*=2;

main()

intk=3;

inta[9][9]={0};

Table(k,a);

=8;

{for(intj=1;

printf("

%3d"

a[i][j]);

printf("

);

思考问题:

1、递归的关键问题在哪里?

2、递归与非递归之间程序的转换?

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

当前位置:首页 > 幼儿教育 > 少儿英语

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

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