第4~5章串和数组自测卷答案 姓名 班级 题号 四 总分 题分20 得分 填空题(每空1分,共20分) 符(长度为0)的串称为空串;由一个或多个空格(仅由空格符)组成的串称 为空白串。 (对应严题集41①,简答题:简述空串和空格串的区别) 2.设S=“A/ document/ Mary. doc”,则 strlen(s)= “的字符定位的位置为 4.子串的定位运算称为串的模式匹配:被匹配的主串称为目标串,_子串称为模式 5.设目标T=" abccdcdccbaa”,模式P=“cdc”,则第_6次匹配成功。 6.若n为主串长,m为子串长,则串的古典(朴素)匹配算法最坏的情况下需要比较字符的总次数为 n-m+1)*m 7.假设有二维数组A6×8,每个元素用相邻的6个字节存储,存储器按字节编址。已知A的起始存储位置 (基地址)为100,则数组A的体积(存储量)为288B:末尾元素Asy的第一个字节地址为 1282 若按行存储时,元素A14的第一个字节地址为_(8+4)×6+1000=1072:若按列存储时,元 素A47的第一个字节地址为(6×7+4)×6+1000)=1276 (注:数组是从0行0列还是从1行1列计算起呢?由末单元为As可知,是从0行0列开始!) 〖00年计算机系考研题〗设数组a[1…60,1…70的基地址为2048,每个元素占2个存储单元,若以列 序为主序顺序存储,则元素a[32,58]的存储地址为_8950 答:不考虑0行0列,利用列优先公式:LOC(a)=LOC(a1,c2)+(c)d-c+1)+ic1)L 得:LOC(a32,58)=2048+(58-1)*(60-1+1)+32-1*2=8950 9.三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分别表示该元素 的_行下标、_列下标和元素值 10.求下列广义表操作的结果: (1) Gethead【(a.b),(c,d)】 ∥头元素不必加括号 (2) Gethead【 GetTail【(ab),(cd)】 (3) GetHead (Get(GetHead【(a,b),(c,d)】】】 (4) Get Tail【 GetHead GetTail【(a,b),(c,d)】】 二、单选题(每小题1分,共15分) (B)1.〖李〗串是一种特殊的线性表,其特殊性体现在 A.可以顺序存储 B.数据元素是一个字符 C.可以链式存储 D.数据元素可以是多个字符
1 第 4~5 章 串和数组 自测卷答案 姓名 班级 题号 一 二 三 四 五 总分 题分 20 15 20 15 30 100 得分 一、填空题(每空 1 分,共 20 分) 1. 不包含任何字符(长度为 0)的串 称为空串; 由一个或多个空格(仅由空格符)组成的串 称 为空白串。 (对应严题集 4.1①,简答题:简述空串和空格串的区别) 2. 设 S=“A;/document/Mary.doc”,则 strlen(s)= 20 , “/”的字符定位的位置为 3 。 4. 子串的定位运算称为串的模式匹配; 被匹配的主串 称为目标串, 子串 称为模式。 5. 设目标 T=”abccdcdccbaa”,模式 P=“cdcc”,则第 6 次匹配成功。 6. 若 n 为主串长,m 为子串长,则串的古典(朴素)匹配算法最坏的情况下需要比较字符的总次数为 (n-m+1)*m 。 7. 假设有二维数组 A6×8,每个元素用相邻的 6 个字节存储,存储器按字节编址。已知 A 的起始存储位置 (基地址)为 1000,则数组 A 的体积(存储量)为 288 B ;末尾元素 A57 的第一个字节地址为 1282 ;若按行存储时,元素 A14 的第一个字节地址为 (8+4)×6+1000=1072 ;若按列存储时,元 素 A47 的第一个字节地址为 (6×7+4)×6+1000)=1276 。 (注:数组是从 0 行 0 列还是从 1 行 1 列计算起呢?由末单元为 A57 可知,是从 0 行 0 列开始!) 8. 〖00 年计算机系考研题〗设数组 a[1…60, 1…70]的基地址为 2048,每个元素占 2 个存储单元,若以列 序为主序顺序存储,则元素 a[32,58]的存储地址为 8950 。 答:不考虑 0 行 0 列,利用列优先公式: LOC(aij)=LOC(ac1,c2 )+[(j-c2)*(d1-c1+1)+i-c1)]*L 得:LOC(a32,58)=2048+[(58-1)*(60-1+1)+32-1]]*2=8950 9. 三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分别表示该元素 的 行下标 、 列下标 和 元素值 。 10.求下列广义表操作的结果: (1) GetHead【((a,b),(c,d))】=== (a, b) ; //头元素不必加括号 (2) GetHead【GetTail【((a,b),(c,d))】】=== (c,d) ; (3) GetHead【GetTail【GetHead【((a,b),(c,d))】】】=== b ; (4) GetTail【GetHead【GetTail【((a,b),(c,d))】】】=== (d) ; 二、单选题(每小题 1 分,共 15 分) ( B )1. 〖李〗串是一种特殊的线性表,其特殊性体现在: A.可以顺序存储 B.数据元素是一个字符 C.可以链式存储 D.数据元素可以是多个字符
(B)2.〖李〗设有两个串p和q,求q在p中首次出现的位置的运算称作 A.连接 B.模式匹配C.求子串 D.求串长 D)3.〖李〗设串sl=' ABCDEFG’,s2= PQRST,函数con(xy)返回x和y串的连接串, subs(s,i,j) 返回串s的从序号i开始的j个字符组成的子串,len(s)返回串s的长度,则con( subs(s1,2,len(2),subs(sl, len(s2),2)的结果串是 A. BCDEF B. BCDEFG C. BCPQRST D. BCDEFEF 解:con(xy)返回x和y串的连接串,即con(xy)=‘ ABCDEFGPQRST'; subs,i,j)返回串s的从序号i开始的j个字符组成的子串,则 subs(sl, 2, len(s2))=subs(sl, 2, 5)="BCDEF, subs(sl, len(s2), 2)=subs(sl, 5, 2EF 所以con(subs(sl,2,len(s2),subs(sl,len(s2),2)=con( BCDEF,'EF)之连接,即 BCDEFEF A)4.〖01年计算机系考研题〗假设有60行70列的二维数组a[1…60,1…70以列序为主序顺序存 储,其基地址为1000,每个元素占2个存储单元,那么第32行第58列的元素a32,58]的存储地址为 (无第0行第0列元素) A.16902B.16904 C.14454 D.答案A,B,C均不对 答:此题与填空题第8小题相似。(57列×60行+31行)×2字节+10000=16902 (B)5.设矩阵A是一个对称矩阵,为了节省存储,将其下三角部分(如下图所示)按行序存放在一维 数组B[1,n(n-1)2]中,对下三角部分中任一元素a(i≤j),在一维数组B中下标k的值是 A.i(i-1)/2+j-1B.i(i-1)/2+j C.i(i+1)2+j-1 D.i(+1)2+j 解:注意B的下标要求从1开始。 先用第一个元素去套用,可能有B和C A 22 再用第二个元素去套用B和C,B=2而C=3(不符) 所以选B n,I a 6.【91初程P78】从供选择的答案中,选出应填入下面叙述?内的最确切的解答,把相应编号写 在答卷的对应栏内。 有一个二维数组A,行下标的范围是0到8,列下标的范围是1到5,每个数组元素用相邻的4个字 节存储。存储器按字节编址。假设存储数组元素A[O,1]的第一个字节的地址是0ε 存储数组A的最后一个元素的第一个字节的地址是A。若按行存储,则A[3,和A[5,3]的第一个字节的 地址分别是_B和C_。若按列存储,则A[7,1]和A[24的第一个字节的地址分别是D和 供选择的答案: A~E:①28②44③76④92⑤108 ⑥116⑦132⑧176⑨184⑩188 答案: ABCDE=83516 7.【94程P12】有一个二维数组A,行下标的范围是1到6,列下标的范围是0到7,每个数组元素用相 邻的6个字节存储,存储器按字节编址。那么,这个数组的体积是_A_个字节。假设存储数组元素A[10 的第一个字节的地址是0,则存储数组A的最后一个元素的第一个字节的地址是B。若按行存储 则A[2,4]的第一个字节的地址是C_。若按列存储,则A[5,7的第一个字节的地址是_D 供选择的答案 A~D:①12②66③72④96⑤114⑥120 ⑦156⑧234⑨276⑩282(11)283(12)288 答案:ABCD=12
2 ( B )2. 〖李〗设有两个串 p 和 q,求 q 在 p 中首次出现的位置的运算称作: A.连接 B.模式匹配 C.求子串 D.求串长 ( D )3. 〖李〗设串 s1=’ABCDEFG’,s2=’PQRST’,函数 con(x,y)返回 x 和 y 串的连接串,subs(s, i, j) 返回串 s 的从序号 i 开始的 j 个字符组成的子串,len(s)返回串 s 的长度,则 con(subs(s1, 2, len(s2)), subs(s1, len(s2), 2))的结果串是: A.BCDEF B.BCDEFG C.BCPQRST D.BCDEFEF 解:con(x,y)返回 x 和 y 串的连接串,即 con(x,y)=‘ABCDEFGPQRST’; subs(s, i, j)返回串 s 的从序号 i 开始的 j 个字符组成的子串,则 subs(s1, 2, len(s2))=subs(s1, 2, 5)=’ BCDEF’; subs(s1, len(s2), 2)=subs(s1, 5, 2)=’ EF’; 所以 con(subs(s1, 2, len(s2)), subs(s1, len(s2), 2))=con(’ BCDEF’, ’ EF’)之连接,即 BCDEFEF ( A )4. 〖01 年计算机系考研题〗假设有 60 行 70 列的二维数组 a[1…60, 1…70]以列序为主序顺序存 储,其基地址为 10000,每个元素占 2 个存储单元,那么第 32 行第 58 列的元素 a[32,58]的存储地址为 。 (无第 0 行第 0 列元素) A.16902 B.16904 C.14454 D.答案 A, B, C 均不对 答:此题与填空题第 8 小题相似。(57 列×60 行+31 行)×2 字节+10000=16902 ( B )5. 设矩阵 A 是一个对称矩阵,为了节省存储,将其下三角部分(如下图所示)按行序存放在一维 数组 B[ 1, n(n-1)/2 ]中,对下三角部分中任一元素 ai,j(i≤j), 在一维数组 B 中下标 k 的值是: A.i(i-1)/2+j-1 B.i(i-1)/2+j C.i(i+1)/2+j-1 D.i(i+1)/2+j 6. 【91 初程 P78】 从供选择的答案中,选出应填入下面叙述 ? 内的最确切的解答,把相应编号写 在答卷的对应栏内。 有一个二维数组 A,行下标的范围是 0 到 8,列下标的范围是 1 到 5,每个数组元素用相邻的 4 个字 节存储。存储器按字节编址。假设存储数组元素 A[0,1]的第一个字节的地址是 0。 存储数组 A 的最后一个元素的第一个字节的地址是 A 。若按行存储,则 A[3,5]和 A[5,3]的第一个字节的 地址分别是 B 和 C 。若按列存储,则 A[7,1]和 A[2,4]的第一个字节的地址分别是 D 和 E 。 供选择的答案: A~E:①28 ② 44 ③ 76 ④ 92 ⑤ 108 ⑥ 116 ⑦ 132 ⑧ 176 ⑨ 184 ⑩ 188 答案:ABCDE=8, 3, 5, 1, 6 7.【94 程 P12】 有一个二维数组 A,行下标的范围是 1 到 6,列下标的范围是 0 到 7,每个数组元素用相 邻的 6 个字节存储,存储器按字节编址。那么,这个数组的体积是 A 个字节。假设存储数组元素 A[1,0] 的第一个字节的地址是 0,则存储数组 A 的最后一个元素的第一个字节的地址是 B 。若按行存储, 则 A[2,4]的第一个字节的地址是 C 。若按列存储,则 A[5,7]的第一个字节的地址是 D 。 供选择的答案 A~D:①12 ② 66 ③ 72 ④ 96 ⑤ 114 ⑥ 120 ⑦ 156 ⑧ 234 ⑨ 276 ⑩ 282 (11)283 (12)288 答案:ABCD=12, 10, 3, 9 解:注意 B 的下标要求从 1 开始。 先用第一个元素去套用,可能有 B 和 C; 再用第二个元素去套用 B 和 C,B=2 而 C=3(不符); 所以选 B = an an an n a a a A ,1 ,2 , 2,1 2,2 1,1
三、简答题(每小题5分,共15分) 1.【其他教材】已知二维数组Am,m采用按行优先顺序存放,每个元素占K个存储单元,并且第一个元 素的存储地址为Loc(al),请写出求Loc(aj)的计算公式。如果采用列优先顺序存放呢? 解:公式教材已给出,此处虽是方阵,但行列公式仍不相同 按行存储的元素地址公式是:Loc(aj)=Loc(a1)+[(i-1)*m+(-1)]*K 按列存储的元素地址公式是:Loc(aj)=Loc(a1)+[(-1)*m+(-1)]*K 2.【全国专升本资格考试】递归算法比非递归算法花费更多的时间,对吗?为什么? 答:不一定。时间复杂度与样本个数n有关,是指最深层的执行语句耗费时间,而递归算法与非递归算法 在最深层的语句执行上是没有区别的,循环的次数也没有太大差异。仅仅是确定循环是否继续的方式不同, 递归用栈隐含循环次数,非递归用循环变量来显示循环次数而已 四、计算题(每题5分,共20分) 1.设s=' LAMA STUDENT,t='GOOD,q= WORKER,求 Replace(s,' STUDENT,q)和 Concat( SubString(s, 6, 2), Concat(t, SubString(s, 7, 8) 解:① Replace(s,' STUDENT,q)=’ LAMA WORKER ②因为 SubString(s,6,2)=‘A'; Substring(s,7,8)=‘ STUDENT Concat(t, SubString(s, 7, 8))=GOOD STUDENT BT LA Concat( SubString(s, 6, 2), Concat(t, SubString(s, 7, 8))='A GOOD STUDENT 2.(P604-18)用三元组表表示下列稀疏矩阵: 00000000 00000-2 03000800 000090 00000000 000000 (1) 00060000 005000 00000000 000000 00000005 000030 20000000 解:参见填空题4.三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分 别表示该元素的行下标 下标和_元素亻 所以(1)可列表为: (2)可列表为: 833578 538652 246 66535 3.(P604-19)下列各三元组表分别表示一个稀疏矩阵,试写出它们的稀疏矩阵
3 三、简答题(每小题 5 分,共 15 分) 1. 【其他教材】已知二维数组 Am,m 采用按行优先顺序存放,每个元素占 K 个存储单元,并且第一个元 素的存储地址为 Loc(a11),请写出求 Loc(aij)的计算公式。如果采用列优先顺序存放呢? 解:公式教材已给出,此处虽是方阵,但行列公式仍不相同; 按行存储的元素地址公式是: Loc(aij)= Loc(a11) +[ (i-1)*m+(j-1) ] * K 按列存储的元素地址公式是: Loc(aij)= Loc(a11) +[ (j-1)*m+(i-1) ] * K 2.【全国专升本资格考试】递归算法比非递归算法花费更多的时间,对吗?为什么? 答:不一定。时间复杂度与样本个数 n 有关,是指最深层的执行语句耗费时间,而递归算法与非递归算法 在最深层的语句执行上是没有区别的,循环的次数也没有太大差异。仅仅是确定循环是否继续的方式不同, 递归用栈隐含循环次数,非递归用循环变量来显示循环次数而已。 四、计算题(每题 5 分,共 20 分) 1. 设 s=’I AM A STUDENT’, t=’GOOD’, q=’WORKER’, 求 Replace(s,’STUDENT’,q) 和 Concat(SubString(s,6,2), Concat(t,SubString(s,7,8)))。 解:① Replace(s,’STUDENT’,q)=’I AM A WORKER’ ② 因为 SubString(s,6,2)=‘A ’;SubString(s,7,8)=‘ STUDENT’ Concat(t,SubString(s,7,8))=’GOOD STUDENT’ 所以 Concat(SubString(s,6,2), Concat(t,SubString(s,7,8)))=‘AGOOD STUDENT’ 2. (P60 4-18)用三元组表表示下列稀疏矩阵: 20000000 00000005 00000000 00060000 00000000 03000800 00000000 00000000 (1) − 00003 0 00000 0 00500 0 00000 0 00009 0 00000 2 (2) 解:参见填空题 4. 三元素组表中的每个结点对应于稀疏矩阵的一个非零元素,它包含有三个数据项,分 别表示该元素的 行下标 、 列下标 和 元素值 。 所以(1)可列表为: (2)可列表为: 8 8 5 3 2 3 3 6 8 5 4 6 7 8 5 8 1 2 3. (P60 4-19)下列各三元组表分别表示一个稀疏矩阵,试写出它们的稀疏矩阵。 6 6 4 1 6 -2 2 5 9 4 3 5 6 5 3
646 455 122 111 2112 249 (1)313 328 444 356 536 437 6116 解:(1)为6×4矩阵,非零元素有6个。(2)为4×5矩阵,非零元素有5个 0200 10000 12000 00090 3000 08006 0004 00700 0060 16000 五、算法设计题(每题10分,共30分) 【严题集4.2③】编写一个实现串的置换操作 Replace(&S,T,V)的算法。 解 int Replace( Stringtype&s, Stringtype T, Stringtype V;/将串S中所有子串T替换为 V并返回置换次数 for(n=0,F=1;i<= Strlen(S) Strlen(T+1;i+)∥注意i的取值范围 if( StrCompare( Substring(s, i, Strlen(D),T)∥找到了与T匹配的子串 ∥分别把T的前面和后面部分保存为head和tail StrAssign(head, SubString(S, 1, i-1)) StrAssign(tail, SubString(s, i+Strlen(t), Strlen(S)-I-Strlen(T)+D)); Str Assign(S, Concat(head, V)) Strassign(S, Concat(S,tail);∥把head,,ail连接为新串 H= Strlen(V),∥当前指针跳到插入串以后 n++ n++ return n 分析+= Strlen(V,这一句是必需的也是容易忽略的如省掉这一句,则在某些情况下,会引起不希望的后果, 虽然在大多数情况下没有影响请思考:设S= place,T=ace,v=face,则省掉i+= Strlen(V,运行时会出现什么 结果? 2.【严题集518⑤】试设计一个算法,将数组An中的元素A0至A|n-1循环右移k位,并要求只用
4 6 116 5 3 6 4 4 4 3 1 3 2 1 12 1 2 2 6 4 6 (1) 4 3 7 3 5 6 3 2 8 2 4 9 111 4 5 5 (2) 解:(1)为 6×4 矩阵,非零元素有 6 个。 (2)为 4×5 矩阵,非零元素有 5 个 五、算法设计题(每题 10 分,共 30 分) 1. 【严题集 4.12③】 编写一个实现串的置换操作 Replace(&S, T, V)的算法。 解: int Replace(Stringtype &S,Stringtype T,Stringtype V);//将串 S 中所有子串 T 替换为 V,并返回置换次数 { for(n=0,i=1;i<=Strlen(S)-Strlen(T)+1;i++) //注意 i 的取值范围 if(!StrCompare(SubString(S,i,Strlen(T)),T)) //找到了与 T 匹配的子串 { //分别把 T 的前面和后面部分保存为 head 和 tail StrAssign(head,SubString(S,1,i-1)); StrAssign(tail,SubString(S,i+Strlen(T),Strlen(S)-i-Strlen(T)+1)); StrAssign(S,Concat(head,V)); StrAssign(S,Concat(S,tail)); //把 head,V,tail 连接为新串 i+=Strlen(V); //当前指针跳到插入串以后 n++; n++; }//if return n; }//Replace 分析:i+=Strlen(V);这一句是必需的,也是容易忽略的.如省掉这一句,则在某些情况下, 会引起不希望的后果, 虽然在大多数情况下没有影响.请思考:设 S='place', T='ace', V='face',则省掉 i+=Strlen(V);运行时会出现什么 结果? 2. 【严题集 5.18⑤】试设计一个算法,将数组 An 中的元素 A[0]至 A[n-1]循环右移 k 位,并要求只用一 0 2 0 0 12 0 0 0 3 0 0 0 0 0 0 4 0 0 6 0 16 0 0 0 1 0 0 0 0 0 0 0 9 0 0 8 0 0 6 0 0 7 0 0
个元素大小的附加存储,元素移动或交换次数为Om) 解 分析:要把A的元素循环右移k位,则A[移至Ak]Ak]移至A[2k]…直到最终回到A0然而这并没有全 部解决问题,因为有可能有的元素在此过程中始终没有被访问过而是被跳了过去分析可知当n和k的最大 公约数为p时,只要分别以A[O]A[]AIp-为起点执行上述算法,就可以保证每一个元素都被且仅被右移 次,从而满足题目要求也就是说,A的所有元素分别处在p个"循环链"上面举例如下 =15k=6,则p=3 第一条链:A]->A[6]A6]->A[12]A12}>A[31A[3>A[9A[9}>A[0“顺便”移动了A[6]、A[2]… 第二条链:A[]->A门7,A[7]->A[3]A[13->A[4]A4}>A[10]A[10}>A[] 第三条链:A[2]->A[8]A[8]->A[41A[4}>A[5A[5>A[1A[->A[2] 恰好使所有元素都右移一次 虽然未经数学证明,但作者相信上述规律应该是正确的程序如下: void rSh(int A[m,intk)∥/把数组A的元素循环右移k位,只用一个辅助存储空间 for(i=l; <=k; 1++) ifn%=0&&k%i=0)p=i/求n和k的最大公约数p for(=0;i<p;i++) j=i; I=(i+k)%n, temp=A[O] lle(l=i) Altemps temp=All A[=A亦l j=;=(+k)%n, ∥循环右移一步 Ai=temp i//fo i//RSh 附加题:利用C的库函数 strlen, strep(或 strncpy)写一个算法 void StrDelete(char *S,int t, int m),删 除串S中从位置开始的连续的m个字符。若i≥ strlen(S),则没有字符被删除;若计m≥ strlen(S),则将 S中从位置i开始直至末尾的字符均被删去。 提示: strlen是求串长 ength)函数: int strlen( char s);//求串的长度 strcpy是串复制copy)函数:char* strcpy( char to, char from;/该函数将串from复制到串 to中,并且返回一个指向串to的开始处的指针
5 个元素大小的附加存储,元素移动或交换次数为 O(n) 解: 分析:要把 A 的元素循环右移 k 位,则 A[0]移至 A[k],A[k]移至 A[2k]......直到最终回到 A[ 0].然而这并没有全 部解决问题,因为有可能有的元素在此过程中始终没有被访问过,而是被跳了过去.分析可知,当 n 和 k 的最大 公约数为 p 时,只要分别以 A[0],A[1],...A[p-1]为起点执行上述算法,就可以保证每一个元素都被且仅被右移 一次,从而满足题目要求.也就是说,A 的所有元素分别处在 p 个"循环链"上面.举例如下: n=15,k=6,则 p=3. 第一条链:A[0]->A[6],A[6]->A[12],A[12]->A[3],A[3]->A[9],A[9]->A[0]. /已“顺便”移动了 A[6]、A[12]… 第二条链:A[1]->A[7],A[7]->A[13],A[13]->A[4],A[4]->A[10],A[10]->A[1]. 第三条链:A[2]->A[8],A[8]->A[14],A[14]->A[5],A[5]->A[11],A[11]->A[2]. 恰好使所有元素都右移一次. 虽然未经数学证明,但作者相信上述规律应该是正确的. 程序如下: void RSh(int A[n],int k)//把数组 A 的元素循环右移 k 位,只用一个辅助存储空间 { for(i=1;i<=k;i++) if(n%i==0&&k%i==0) p=i;//求 n 和 k 的最大公约数 p for(i=0;i<p;i++) { j=i;l=(i+k)%n;temp=A[i]; while(l!=i) { A[j]=temp; temp=A[l]; A[l]=A[j]; j=l;l=(j+k)%n; }// 循环右移一步 A[i]=temp; }//for }//RSh 附加题: 利用 C 的库函数 strlen, strcpy(或 strncpy)写一个算法 void StrDelete(char *S,int t,int m) ,删 除串 S 中从位置 i 开始的连续的 m 个字符。若 i≥strlen(S),则没有字符被删除;若 i+m≥strlen(S),则将 S 中从位置 i 开始直至末尾的字符均被删去。 提示:strlen 是求串长(length)函数:int strlen(char s); //求串的长度 strcpy 是串复制(copy)函数:char *strcpy(char to,char from); //该函数将串 from 复制到串 to 中,并且返回一个指向串 to 的开始处的指针