编程珠玑课后习题答案 第四章 编写正确的程序

news/2024/12/2 12:36:09/

1. 尽管我们的二分搜索证明历经曲折,但是按照某些标准来衡量还是不够完善。你会如何证明改程序没有运行时错误(例如除数为 0、数值溢出、变量值超出声明的范围或者数组下标越界)呢?如果有离散数学的基础知识,你能否使用逻辑系统形式化来证明?

为了证明程序不会出现溢出错误,我们在不变式中添加条件 0 <= l <= n 和 -1 <= u <=n,这样我们就可以限定 l+u 的范围了。这两个条件还可以用于证明不会访问数组边界之外的元素。如果像书中 9.3 节一样定义假想的边界元素 x[-1] 和 x[n],那么我们就能将 mustbe(l,u)形式化地定义为 x[l-1] 和 x[u+1]>t。

2. 如果原始的二分搜索对你来说太过容易了,那么请试试这个演化后的版本:把 t 在数组 x 中第一次出现的位置返回给 p(如果存在多个 t 的话,原始的算法会任意返回其中的一个)。要求代码对数组元素进行对数次比较(该任务可以在 log2n 次比较之内完成)。

l = -1; u = n
while l+1 != um = (l + u) / 2if x[m] < tl = melseu = m
p = u
if p >= n || x[p] != tp = -1

如果 t 在 x 中,那么将 p 置为 t 第一次出现的下标;如果 t 不在数组中,则将 p 置为 -1。

3. 编写并验证一个递归的二分搜索程序。代码和证明中的哪些部分与迭代版本的二分搜索程序相同?哪些部分发生了改变?

4. 给你的二分搜索程序添加虚拟的“计时变量”来计算程序执行的比较次数,并使用程序验证技术来证明其运行时间确实是对数的。

5. 证明下面的程序在输入 x 为正整数时能够终止。

while x != 1 doif even(x)x = x / 2elsex = 3 * x + 1

如果你解决了这个问题,请到最靠近的数学系申请一个博士学位。

6. [C.Scholten] David Gries 在其 Science of Programming 中将下面的问题称为“咖啡罐问题”。给定一个盛有一些黑色豆子和一些白色豆子的咖啡馆以及一大堆“额外”的黑色豆子,重复下面的过程,直至罐中仅剩一颗豆子为止:从罐中随机选取两颗豆子,如果颜色相同,就将它们都扔掉并且放入一个额外的黑色豆子;如果颜色不同,就将白色的豆子放回罐中,而将黑色的豆子扔掉。需要证明该过程会终止。最后留在罐中的豆子颜色与最初罐中白色豆子和黑色豆子的数量有何函数关系?

由于每一步都使得罐中的豆子减少一粒,所以该过程能够终止。我们每一步都从咖啡罐中拿掉零个或者两个白色豆子,所以白色豆子的奇偶性保持不变。因此,当且仅当罐中最初的白色豆子个数为奇数时,最后留下的豆子才可能是白色的。

7. 一位同事在编写一个在位图显示器中画线的程序时遇到了下面的问题。n 对实数(ai,bi)构成的数组定义了 n 条直线 yi = ai + bi。当 x 位于[0,1]内时,对于区间[0,n-2]内的所有 i,这些线段按 yi < yi+1 排序。用更形象的话说,这些线段在垂直方向上不交叉。给定一个满足 0 <= x <= 1 的点(x,y),他需要确定包围这个点的两条线段。他该如何快速解决该问题呢?

构成梯级的线段在 y 方向上是递增的,因此我们可以通过二分搜索来找到包含给定点的两条线段。搜索中的基本比较说明了点在给定线段的下方、里面还是上方。应如何编写该函数?

8. 二分搜索一般比顺序搜索要快:在含有 n 个元素的表中查找,二分搜索需要大约 log2n 次比较,而顺序搜索需要大约 n/2 次比较。通常情况下这已经足够快了,但是有些情况下,二分搜索必须执行得更快。虽然我们无法减少由算法决定的对数级的比较次数,你可以重新编写代码使之执行得更快吗?为明确起见,假定你需要搜索一个包含 1 000 个整数的有序表。

i = 512
l = -1
if x[511] < tl = 1000 - 512
while i != 1i = i / 2if x[l+i] < tl = l + i
p = l + i
if p > 1000 || x[p] != tp = -1

程序代码将确保 i 总是 2 的幂。该性质很容易保持,但是一开始难以获得(因为数组的大小 n 等于 1 000)。因此在程序的开始部分先使用了赋值语句和 if 语句,以确保初始的搜索范围大小为 512,即小于 1 000 的数中最大的 2 的幂。这样 l 和 l+1 一起要么表示 -1…511,要么表示488…1 000。使用这个新的范围表示方法转换初始的二分搜索程序。

因为 i 在程序中只有 10 个互不相同的值,所以我们可以将它们全部写在代码中,从而避免在运行时重复计算。代码如下:

l = -1
if (x[511] < t) l = 1000 - 512
if (x[l+256] < t) l += 256
if (x[l+128] < t) l += 128
if (x[l+64] < t) l += 64
if (x[l+32] < t) l += 32
if (x[l+16] < t) l += 16
if (x[l+8] < t) l += 8
if (x[l+4] < t) l += 4
if (x[l+2] < t) l += 2
if (x[l+1] < t) l += 1
p = l + 1
if p > 1000 || x[p] != tp = -1

9. 完成以下程序验证练习,准确说明以下每个程序片段的输入、输出动作,并证明代码可以完成其任务。第一个程序实现向量加法 a = b + c。

i = 0
while i < na[i] = b[i] + c[i]i = i + 1

(该代码和下面的两个代码片段使用末尾带有自增运算的 while 循环展开了 “for i = [0,n)”循环)。下面的代码片段计算数组 x 中的最大值。

max = x[0]
i = 1
while i < n doif x[i] > maxmax = x[i]i = i + 1

下面的顺序搜索程序返回 t 在数组 x[0…n-1]中第一次出现的位置。

i = 0
while i < n && x[i] != ti = i + 1
if i >= np = -1
elsep = i

下面的程序以正比于 n 的对数的时间计算 x 的 n 次方。该递归程序的编码和验证很简单;其迭代版本比较复杂,留作附加题。

function exp(x, n)pre n >= 0post result = x ^ n
if n = 0return 1
else if even(n)return square(exp(x, n/2))
elsereturn x * exp(x, n-1)

10. 在二分搜索函数中引入错误,观察验证错误代码时这些引入的错误是否会(以及如何)被捕获?

11. 使用 C 或 C++ 编写递归的二分搜索函数并证明其正确性,要求函数的声明如下:int binarysearch(DataType x[], int n)单独使用该函数,不要调用其他任何递归函数。

参考答案 11.14中把数组指针传递给 swap 函数的递归函数。


http://www.ppmy.cn/news/498806.html

相关文章

是时候适配android14了

1、原来老项目中有用到前台Service的功能的app&#xff0c;需要在14当中制定服务类型&#xff0c;类型分类如下所示&#xff1a; 为了帮助开发者更有目的地定义面向用户的前台服务&#xff0c;Android 10 在 <service> 元素内引入了 android:foregroundServiceType 属性…

电脑嘟一声,然后卡顿的解决办法

网上关于此类的解释大都是硬盘坏了&#xff0c;但用硬盘监测工具&#xff0c;譬如CrystalDiskInfo.exe看到硬盘的状态都是没有问题。 后来找到真正的原因是电源选项设置问题&#xff0c;之前是1分钟关闭硬盘&#xff0c;改成永远不关闭即可。

解决电脑卡顿问题

1.解决电脑卡顿问题 a.检查 b.修复 c.重启 2.查看电脑是否正版 a.输入命令 b.显示信息

电脑系统卡顿,怎么解决

最近感觉系统卡卡的 别抓心挠肝的了 今天小编教你如何应对 No.1 设置任务管理器 1.按住CtrlShiftESC&#xff0c;打开任务管理器。查看占用CPU、内存、磁盘、比例较高的程序结束进程。&#xff08;有时软件异常导致CPU使用率较高就可以选择禁用它&#xff09; 2.选择启动…

电脑卡慢原因之磁盘占用100%

电脑刚重装完系统没多久就变得卡慢了&#xff0c;前几天一直凑合着用着&#xff0c;今天实在受不了了&#xff0c;点一下鼠标反应好长时间&#xff0c;还让不让人好好玩耍了。今天就花了一些时间彻底解决一下这个问题。 遇到这种情况&#xff0c;我首先查看了一下资源管理器&am…

电脑卡怎么办,简单步骤让电脑变快

随着时代的发展&#xff0c;电脑成了生活中必不可少的部分。但是&#xff0c;当你的电脑变慢了&#xff0c;怎么办呢&#xff1f;直接重新安装系统吗&#xff1f;那可能不是明智的选择&#xff01;电脑用的时间越长就越卡&#xff0c;这是很正常的现象&#xff0c;基本上是每个…

计算机搜索功能卡,电脑卡

本词条缺少概述图&#xff0c;补充相关内容使词条更完整&#xff0c;还能快速升级&#xff0c;赶紧来编辑吧&#xff01; 电脑使用过程中由内存&#xff0c;运行&#xff0c;硬件等原因造成的电脑反映缓慢现象。 中文名 电脑卡 类 型 硬件领 域 计算机 性 质 名词 电脑…

解决电脑卡顿的一系列操作

本篇从别处回答复制的&#xff0c;主要用作自己的备忘。&#xff08;不一定全部都要修改&#xff0c;我改完一项虚拟内存后就不怎么卡了&#xff09; 而且尝试完之后电脑的确不怎么卡了。 copy from :http://ask.zol.com.cn/x/1174226.html 一、清理磁盘和整理磁盘碎片。 1、在…