《算法导论》[第2章] 算法入门-[2.1] 插入排序

|概念回顾|

循环不变式的三个性质:

  1. 初始化:它在循环的第一轮迭代开始之前,应该是正确的。
  2. 保持:如果在循环的某一次迭代开始之前它是正确的,那么,在下一次迭代开始之前,它也应该保持正确。
  3. 终止:当循环结束时,不变式给了我们一个有用的性质,它有助于表明算法是正确的。

伪代码中的约定:

  1. 书写上的“缩进”表示程序中的分程序(程序块)结构。
  2. while,for,repeat等循环结构和if,then,else条件结构与Pascal中相同。
  3. 符号 "▷” 表示后面部分是个注释。
  4. 多重赋值 i←j←e 是将表达式e的值赋给变量i和j;等价于 j←e,再进行赋值 i←j。
  5. 变量(如i,j和key等)是局部给定过程的。
  6. 数组元素是通过“数组名[下标]”这样的形式来访问的。
  7. 复合数据一般组织成对象,它们是由属性(attribute)和域(field)所组成的。
  8. 参数采用按值传递方式:被调用的过程会收到参数的一份副本。
  9. 布尔运算符"and”和"or”都是具有短路能力。

|习题解答|

2.1-1 以图2-2为模型,说明INSERTION-SORT在数组A=<31,41,59,26,41,58>上的执行过程。

31 41 59 26 41 58
31 41 59 26 41 58
31 41 59 26 41 58
26 31 41 59 41 58
26 31 41 41 59 58
26 31 41 41 58 59

注:红色表示要准备插入的数,蓝色表示与红色数字比较过的数。

 

2.1-2 重写过程INSERTION-SORT,使之按非升序(而不是按非降序)排序。

伪代码如下:

INSERTION-SORT(A)
     for j←to length[A]
         do key←A[J]
         i←j-1
         while i>0 and A[i]<key
             do A[i+1]←A[i]
             i←i-1
         A[i+1]←key

2.1-3 考虑下面的查找问题:

输入:一列数A=<a1,a2,…,an>和一个值V。

输出:下标i,使得V=A[i],或者当V不再A中出现时为NIL。

写出针对这个问题的线性查找的伪代码,它顺序地扫描整个序列以查找V。利用循环不变式证明算法的正确性。确保所给出的循环不变式满足三个必要的性质。

伪代码如下:

LINEAR-SEARCH(A,V)
     flag←0
     for i←1 to length[A]
         do if A[i]==V
            then print i
             flag←1
     if flag==0
        then print NIL

循环不变式的证明如下:

初始化:首先,先来证明在第一轮迭代之前,它是成立的。此时,flag初始化为0,表示未找到这样一个小标i,使得A[i]=V.若为1,则表示已找到一个或多个这样的下标。那么,很显然,在还未开始之前flag=0是正确的,也就证明了循环不变式在循环的第一轮迭代开始之前是成立的。

保持:接下来证明每一轮循环都能使循环不变式保持成立。我们看到,在第一个for循环体内,随着i逐个从1到遍历完整个数列的过程中,只要有一个下标i,使得A[i]等于V,那么在输出i的同时,将flag重新标记为1,表示已找到。无论接下来是否还有这样满足条件的i出现,flag的值不变,仍为1,反之,若遍历完之后,没有找到这样的一个i,那么flag在这个for循环中未做任何改变,仍为0。所以,循环不变式的第二个性质也成立。

终止:对此线性查找算法来说,当i大于length[A]的值(即遍历完整个A数列后),for循环结束。这时,如果flag未改变(即flag=0),则说明未能找到这样的下标i,输出NIL;反之,若已在for循环中被修改为1,则不会运行此步语句,这也就意味着该算法是正确的。

 

2.1-4 有两个各存放在数组A和B中的n位二进制整数,考虑它们的相加问题。两个整数的和以二进制形式存放在具有(n+1)个元素的数组C中。请给出这个问题的形式化描述,并写出伪代码。

形式化描述如下:

首先,初始化数组C,使其n+1各元素的值都为0。接着,利用for循环用i同时从n到1反向遍历A、B数组,每遍历一步,作一个判断:若A[i]+B[i]>1,则C[i]=C[i]+1;反之,C[i+1]=A[i]+B[i]。最后,当i=0时,for循环结束,此时C数组中存储的即是所求的结果。

伪代码如下:

BINRARY-SUM(A,B,C)
     for i←1 to n+1
         do C[i]←0
     for i←n to 1
         do if A[i]+B[i]>1
               then C[i]=C[i]+1
               else C[i+1]=A[i]+B[i]
posted @ 2010-03-09 21:58  timebug  Views(1550)  Comments(7Edit  收藏  举报