chap2 习题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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;