1、程序设计方法学习题汇总一、简答题:1) 何谓 Proper 程序?试举一例。答:一个框图程序,若满足:i)一个入口,一个出口;ii)每个结点总有一条从入口到出口的路径通过它。则称其为 Proper 程序。例:2) 何谓 prime 程序?试举一例。答:Prime 程序又称初等程序、基本程序。是 Proper 程序且其中不包括由二个以上结点组成的 Proper 程序。即最小的 Proper 程序。例:3) 给出 Hoare 关于程序部分正确和完全正确的定义。答:给定 Spec( , ),若对输入 x 满足 (x) ,则程序 S 计算终止,且 (x , z)满足。称 S 关于( , ) 是完全正确
2、的。记为S 。给定 Spec(, ),若对输入 x 满足 (x) ,当程序 S 计算终止时,满足 (x , z)。称 S 关于( , ) 是部分正确的。记为S。4) Hoare 关于程序部分正确和完全正确的定义有什么区别?为什么在证明程序 S 是完全正确时可以分别证明部分正确和终止?答:Hoare 关于程序部分正确和完全正确的定义的区别在于程序的部分正确不保证程序的终止,而程序的完全正确保证程序即是部分正确的,同时又是终止的。因为一个程序 S 是完全正确的等价于该程序是部分正确的同时又是终止的,因此在证明程序 S 是完全正确时可以分别证明部分正确和终止。5) 何谓抽象数据类型(ADT) ,它解
3、决了程序设计中的什么问题?答:根据数据抽象的原则,符合“一个值集和作用在值集上的操作集”的数据类型,称为 ADT。ADT 解决了程序设计中如何描述大型程序的形式规范问题。其优点是:支持模块化、封装性、简化对正确性的验证、支持复用,提高软件质量。6) 面向对象的程序设计的本质是什么?与模块化程序设计的最大区别是什么?答:面向对象程序设计的本质是以对象为软件的构件,以类来叙述对象的行为,以消息来引发对象的行为。与模块化程序设计相比,面向对象的程序设计将要构造的软件系统表示为对象集,每个对象是一组数据及其作用在其上的一组基本操作封装而成的实体,对象间通过消息传递实现联系。而模块化是把大程序划分成若干
4、模块,每个模块完成一个子功能,模块间相互协调,共同完成特定功能,其实质是把复杂问题分解成许多容易解决的小问题。7) 令 , 是程序 S 的前置谓词和后置谓词,, 与 S 是一个什么关系?答:Spec 可以表示为二元组( ,) ,称 是初始(前置)断言, 是结果(后置)断言。称S为 S 关于 Spec(,) 的程序断言。其含义是:若 S 执行前 为 T,那么 S 的执行一定终止,且终止时 为 T。8) 叙述最弱前置谓词 WP 的定义。试举一例。答:设 S 是一个程序(语句) , 是一个后置谓词,定义最弱前置谓词 WP(S,)为:满足 S 从其中任一状态开始执行,必定在有限的时间内终止。且满足 的
5、所有状态的集合。例:S1: i:=i+1;1:i10WP(S1, 1)(i9)9) 可以用顺序语句“;”和重复语句“WHILE-DO”来描述判定语句“IF_THEN_ELSE”的功能吗?为什么?答:可以,例如可以将判定语句“if C then A; else B; ”用重复语句表示为:While C doA;While !C doB;10) 计算非负整数 x 和 y 的最大公约数:gcd1(x,y) if x=0 then yelse if y0 doIf L=1Then g1;Else if L=2Then g2;Else if L=nThen gn;Else I;F ;,IF-THEN-E
6、LSE,WHILE F 与 P 等价。2) 试证 WP(S,12) WP(S,1)WP(S,2)其中 S 是程序,1,2 是其后置谓词。证: (12) 1 由单调率,WP(S,12) WP(S,1)同理:WP(S,12) WP(S,2) A B,A C,有 A (BC ) 结论成立。3) 若 P、Q 是任意语句 S 的任意两个后置谓词,试证:WP (S , P Q) WP (S , P)WP (S , P) WP (S , P Q)证:i) (PQ) P 由单调率,WP(S,P Q) WP(S,P)ii) P P Q 由单调率,WP(S,P) WP(S,PQ)4) a下述框图程序计算 x1 除
7、以 x2,试用 Floyd 归纳断言法证明其关于规范(,)是部分正确的。其中 (x):x1=0 x2=0, (x,z):x1=z1*x2+z20=X2(z1,2):=(y1,2)FTb若 (x,z) 不变,(x) 如何改动才能使上述框图程序关于规范( ,)是完全正确的,为什么?( 给出用 Floyd 归纳断言法的证明)证:a ( 1)置切割点 Ba,切割路径为:(ABa): R:T r :(0,x1)(Ba Ba ): R:y2=x2 r:(y1+1,y2-x2)(Ba C): R:y2=0x2=0C:(x,z)x1=z1*x2+z2 0=0(3)证明各路径上的验证条件为 true:ABa (
8、x) T IA(x,0,x1)(x) T x1=0 x2=0IA(x,0,x1) x=0此验证条件成立:Ba Ba IA(x,y1,y2) R (x,y) IA(x,r (x,y) IA(x,y1+1,y2-x2)IA(x,y1,y2) R (x,y) x1=y1*x2+y2y2=0 y2=x2x1=y1*x2+y2y2=x2IA(x,r (x,y) x1=(y1+1)*x2+(y2-x2)(y2-x2)=0x1=y1*x2+y2y2=x2此验证条件成立:Ba C IA(x,y1,y2) R(x,y) (x,z)R(x,y) y2=0 y2 0x20 能使上述框图关于规范(,)是完全正确的。证
9、明如下:(1) 置切割点 Bb,切割路径为:(ABb): A R :T r:(0,x1)(BbBb ): B R :y2-x2=x2 r:(y1+1,y2-x2)(BbC ): B R :y2-x2=0x20B: q(x,y) y2=x2y1=0u(x,y) y2-x2(2) 证明 q 是良断言q(x,y) y2=x2 y1=0:(x) R (x) q(x,0,x1)x1=0x20 0=x2y1=0y2-x2=x2 y2-x2=x2y1+1=0 ,成立(3) 证明 u(x,y) y2-x2 是良函数取 W=N 及 =x2y1=0 y2-x2=0x2,y2 均为正整数,y2-x2N(4) 验证条
10、件:循环为 BbBbxyq(x,y) R (x,y) ui(x,r (x,y)=x2y1=0y2-x2=x2 (y2-x2)-x2(y2-x2)-x2 成立 程序关于(N,)是终止的,再加上部分正确 该程序完全正确5) 下述框图程序计算 x!,试用 Floyd 归纳断言法证明关于规范( ,)是部分正确的。其中 (x):x=0, (x,z):z=x!.(y1,2):=(0,1) (y1,2):=(y1+,(y1+)*y2) Y1=XZ:=Y2FT6) 试给出计算 s xi 10 x20(y1,y2):=(x1,0);while x20 x20(y1,y2,y3):=(x1,0,x2);while
11、 y3=0:z=1/ni:00)的最小值的规范(,) ,循环不变式 P,有界函数 t 及其带循环程序 S。答:n0:(i:01,f n=fn-1+fn-2试设计计算 Fibonacci 序列的规范( ,) ,循环不变式 P,有界函数 t 及其带循环程序 S。答:n1:1y THEN x:=x-y ELSE y:=y-x,后置谓词 :x0 y0。试求其最弱前置谓词WP(S,)。答:WP(s, ) (xyxy WP(“x:=x-y”,x0y0) (x0y0)true(xy x-y0y0) (x0y-x0)true(xy xyy0) (x0yx)x0 y0 true6) 设前置谓词 :T 和后置谓词
12、 :zyz:=yFI证明:i) WP(z:=x, )=WP(z:=x, z0 n N (N 是整数集):0= f (i) )要求: 1)给出循环不变式 P、有界函数 t 及程序 S。2)证明 S 关于(,,P ,t)是完全正确的。答:1):n0 n N:0=fi)S:m,k:=-, 0DO kmm=fkFIk:=k+1ODP:0=fi)t:n-i8) 设程序 S: IF ab THEN a:=a-b ELSE b:b-a后置谓词 :a0b0 试求其最弱前置谓词 WP(S,) 。(答案同第 5 题)9) 试设计在数组 b0 . n-1(n0)中寻找 x 的位置 I,且若 x 不在 b 中,则置
13、I 的值为 n 的程序规范(,),循环不变式 P,有界函数 t 及其带循环程序 S。答: :T:(0=0; y=0; X?(x,y)-y1,y2:int; y1:=x; y2:=y;y1y2- *y1y2-y1:= y1 y2 y2y1-y2:=y2-y1; X!y1 | X:USER13) 试用 Hoare 的 CSP 构造一个计算 n!的程序。答:s:*n:int; X?n-s:int; i:=1; s:=1; *i s:=s*i; i:=i+1;X!s | X:USER14) 试用 Hoare 的 CSP 构造队列进程 Buffer。 (先进先出)答:Buffer=queue(0.99)
14、 char; head, tail: int; head:=-1; tail:=-1Push=*c:char;X?c-tail=99-!failed tailtail:=tail+1; X!queue(tail)Pop=*head=tail-!failed head tail-X?queue(head); head:=head+1push:push |pop:pop15) 试用 Hoare 的 CSP 构造堆栈进程 Stack。 (后进先出)答:STACK=stack(0.99): char; top:int; top:=0PUSH=*c:char; X?c-top=99-!failed topX!stack(top); top:=top+1POP=*top=0-!failed top0-top:=top-1; X?stack(top)push:push |pop:pop