chap2 习题

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第二章递归与分治策略

习题2-2 7个二分搜索算法

1)与教材中的算法BinarySearch相比,数组段左、右游标left和right的调整不正确,导致陷入死循环。

2)与教材中的算法BinarySearch相比,数组段左、右游标left和right的调整不正确,导致当x=a[n-1]时返回错误。

3)与正确算法BinarySearch5相比,数组段左、右游标left和right的调整不正确,导致当x=a[n-1]时返回错误。

4)与正确算法BinarySearch5相比,数组段左、右游标left和right的调整不正确,导致陷入死循环。a 5)算法正确,且当数组中有重复元素时,返回满足条件的最右元素。

6)与正确算法BinarySearch5相比,数组段左、右游标left和right的调整不正确,导致当x=a[n-1]时返回错误。

7)与正确算法BinarySearch5相比,数组段左、右游标left和right的调整不正确,导致当x=a[0]陷入死循环。

习题2-30 输油管道最佳布局问题

设M口油井的位置分别为p i=(x i,y i),i=1,…,n。由于主

输油管道是东西向的,因此可用其主轴线的y 坐标唯一确定其位置。主管道的最优位置y 应使()∑=n

i i y y d 1,达到最小,其中

d (y ,y i )=| y -y i |。由带权中位数问题的解答即知,y i ,i =1,…,n 的中位数y k 即为输油管道问题的最忧解。用任何—个线性时间找中位数算法均可在o (n )时间内解此问题。

习题2-34 构造Gray 码的分治算法

考察n=1,2,3的简单情形:

n=1 0,1

n=2 00,01,11,10

n=3 000,001,011,010,110,111,101,100

设n 位Gary 码序列为G(n),G(n)以相反顺序排列的序列为G -1

(n)。从上面的简单情形可以看出G(n)的构造规律:G(n+1)=0G(n)1G -1(n)。

注意到G (n )的最后一个n 位串与G -1(n)的第一个n 位串相同,可用数学归纳法证明G(n)的上述构造规律。由此规律容易设计构造G(n)的分治法如下。 void gray(int n)

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

gray(n-1);

for(int k=1<<(n-1),i=k;i>0;1--)a[2*k-i+1]=a[i]+k; }

上述算法中将n位(0,1)串看作是二进进制整数,第i个串存储在a [i]k中。完成计算后,由out输出Gray码序列。

void out(int n)

{

char str[32];

int m=1<

for (int i=1;i

_itoa(a[i],str,2);

int s=strlen(str);

for(int j=0;j

cout<

}

cout<

}

习题2-35 网球循环赛日程表

用分治法,教材中的分治法应描述如下:

void tourna(int n)

{

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

tourna(n/2);

copy(n);

}

其中,算法copy将左上角递归计算出的小块中的所有数字按其相对位置抄到右下角,将右上角小块中所有数字加n/2后按其相对位置抄到左下角,将左下角小块中的所有数字按其相对位置抄到右下角,这样就完成了比赛日程表。void copy(int n)

{

int m=n/2;

for(int i=1;i<=m;i++)

for(int j=1;j<=m;j++){

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

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

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

}

}

对于一般的正整数n,当n是奇数时,增设一个虚拟选

手n +1,将将问题转换为n是偶数的情形。当选手与虚拟选手比赛时,表示轮空。因此只要关注n为偶数的情形即可。

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

当n/2为奇数时,递归返回的轮空的比赛要做进一步处理。其中一种处理方法是在前n/2轮比赛中让轮空选手与下一个未参赛选手进行比赛。

一般情况下的分治法tournament可描述如下。

void tournament(int n)

{

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

if(odd(n)){tournament(n+1);return;}

tournament(n/2);

makecopy(n);

}

bool odd(int n)

{

return n &1;

}

其中,算法makecopy与算法copy类似,但要区分n/2为奇数或偶数的情形。

void makecopy(int n)

{

if(n/2>1&&odd(n/2)copyodd(n);

else copy(n);

}

算法copyodd实现n/2为奇数时的复制。

void copyodd(int n)

{

int m=n/2;

for(int i=1;i<=m;i++){

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

}

for(i=1;i<=m;i++){

for(int j=1;j<=m+1;j++){

if(a[i][j]>m){a[i][j]=b[i];a[m+i][j]=b[i]+m)%n;}

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

}

for(j=2;j<=m;j++={

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

a[b [i+j-1]][m+j]=I;

相关文档
最新文档