算法导论第二章第一节答案

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

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]

do A[i+1]←A[i]

i←i-1

A[i+1]←key

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

输入:一列数A=和一个值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]

问题描述:

有两个各存放在数组A和B中的n位二进制整数,考虑它们的相加问题。两个整数的和以二进制形式存放在具有(n+1)个元素的数组C中。

问题思考:

先假设整数的二进制数组中,高位在前,低位在后,所以得从后面往前面加——即从低位往高位的顺序加,即循环顺序应为从大到小(n到1)。主要注意的一个问题就是进位的处理,当低位A[i]+B[i]>1时,就会向高位推送一个进位1,那么对于下一次的相加就应该有:

A[i-1]+B[i-1]+进位。

这里把进位描述为carry_flag,并将其初始化为0。

那么就有通用表达式:C[i+1]=(A[i]+B[i]+carry_flag)%2,

这里之所以对2取余,是因为二进制只有0,1(貌似这句话多余了);之所以是C[i+1],而不是C[i],是因为C[n+1](即整数的二进制表示的最低位)的值应该是(A[n]+B[n])%2 的结果,依次类推就有了上面的那个通用表达式,记得每次加完之后都要更新carry_flag。

伪代码:

BINARY-ADD(A,B,C,n)

▷这里假设整数的二进制表示中,高位在前,低位在后

carry_flag ← 0

for j ← n to 1

do key ← A[j]+B[j]+carry_flag

C[j+1] ← key mod 2

if key > 1

carry_flag ← 1

else

carry_flag ← 0

C[0] ← carry_flag

C/C++ 代码:

view sourceprint?

#include

void binary_add(int* a, int *b, int *c, int length){

int i = 0;

int carry_flag = 0;

for(i=length-1; i>=0; i--){

int tmp = a[i]+b[i]+carry_flag;

c[i+1] = tmp % 2;

if(tmp>1){

carry_flag = 1;

}else{

carry_flag = 0;

}

}

c[0]=carry_flag;

}

void main(){

int i = 0;

int length = 0;

int A[8] = {1,0,1,1,1,0,0,1}; //185的二进制形式,高位在前,低位在后 int B[8] = {1,1,0,0,1,0,1,1}; //203的二进制形式,高位在前,低位在后 int C[9] = {0};

length = sizeof(A)/sizeof(int);

binary_add(A,B,C,length);

for(i=0;i<=length;i++){

printf("%d,",C[i]);

}

}

/*----------------------

* 输出结果为:

* 1,1,0,0,0,0,1,0,0

* 388的二进制表示形式

-------------------------*/

JAVA 代码:

view sourceprint?

public class Test{

int[] A = {1,0,1,1,1,0,0,1}; //185的二进制形式,高位在前,低位在后 int[] B = {1,1,0,0,1,0,1,1}; //203的二进制形式,高位在前,低位在后 int[] C = {0,0,0,0,0,0,0,0,0};

private void binary_add(int[] a, int[] b, int[] c, int length){ int carry_flag = 0;

for(int i=length-1; i>=0; i--){

int tmp = a[i]+b[i]+carry_flag;

c[i+1] = tmp % 2;

if(tmp>1){

carry_flag = 1;

}else{

carry_flag = 0;

}

}

c[0]=carry_flag;

相关文档
最新文档