软考初级程序员下午题(13)

试题一

阅读下列算法说明和算法,将应填入______处的语句填写完整。
[说明]
实现连通图G的深度优先遍历(从顶点v出发)的非递归过程。
[算法]
第一步:首先访问连通图G的指定起始顶点v。
第二步:从v出发,访问一个与v______p,再从顶点p出发,访问与p______顶点q,然后从q出发,重复上述过程,直到找不到存在______的邻接顶点为止。
第三步:回退到尚有______顶点,从该顶点出发,重复第二、三步,直到所有被访问过的顶点的邻接点都已被访问为止。
因此,在这个算法中应设一个栈保存被______的顶点,以便回溯查找被访问过顶点的未被访问过的邻接点。

试题二

阅读以下函数说明和C语言函数,将应填入______处的字句填写完整。
[函数1说明]
函数palindrome(char s[])的功能是:判断字符串s是否为回文字符串。若是,则返回0,否则返回-1。若一个字符串顺读和倒读都一样时,则可称该字符串是回文字符串。例如,“LEVEL”“是回文字符串,而“LEVAL”不是。

 [函数1]
    int palindrome(char s[]){
    char*pi,*pj;
    pi=s;pj=s+strlen(s)-1;
    while(pi<pj&&______){
    pi++;pj--;
    }
    if(______)return -1;
    else return 0;
    }
[函数2说明]
函数f(char*str, char del)的功能是:将非空字符串str分割成若干个子字符串并输出,del表示分割时的标志字符。
例如,若str的值为“33123333435”,del的值为“3”,调用此函数后,将输出3个子字符串,分别为“12”、“4”和“5”。
[函数2]
void f(char*str,char del){
int i,j,len;
len=strlen(str);
i=0;
while(i<len){
While(______) i++;   //忽略连续的标志字符
//寻找从str[i]开始直到标志字符出现的一个子字符串
j=i+1;
while(str[j]!=del && str[j]!='\0') j++;
______='\0';   //给找到的字符序列置字符串结束标志
printf("%s/t",&str[i]);
______;
}
}

试题三

阅读以下函数说明和C语言函数,将应填入______处的字句填写完整。
[说明]
本题中的函数encode()和decode()分别实现对字符串的变换和复原。其中变换函数encode()顺序考查已知字符串的字符,按以下规则逐组生成新字符串。
(1)若已知字符串的当前字符不是数字字符,则将该字符复制于新字符串中。
(2)若已知字符串的当前字符是一个数字字符,且它之后没有后继字符,则简单地将它复制到新字符串中。
(3)若已知字符串的当前字符是一个数字字符,并且还有后继字符,设该数字字符的面值为n,则将它的后继字符(包括后继字符是一个数字字符)重复复制n+1次到新字符串中。
(4)以上述一次变换为一组,在不同组之间另插入一个下画线“_”用于分隔。例如,encode()函数对字符串26a3t2的变换结果为666_a_tttt_2。
复原函数decode()做与变换函数encode()相反的工作。即复制不连续相同的单个字符,而将一组连续相同的字符(不超过10个)变换成一个用于表示重复次数的数字符和一个重复出现的字符,并在复原过程中略过变换函数,为不同组之间添加一个下画线字符。
假定调用变换函数encode()时的已知字符串中不含下画线字符。

 [函数]
    int encode(char*instr,char*outstr){
    char*ip,*op,c;int k,n;
    ip=instr;op=outstr;
    while(*ip){
    if(*ip>='0'&&*ip<='9'&&*(ip+1)){
    n=______;
    c=______;
    fbr(k=0;k<n;k++)
    *op++=c;
    }
    else______;
    *op++='_';
    ip++;
    }
    if(op>outstr)op--;
    ______;
    return op-outstr;
    }
    int decode(char*instr,char*outstr){
    char*ip,*op,c;int n;
    ip=instr;op=outstr;
    while(*ip){
    c=*ip;n=0;
    while(*ip==c && n<10){
    ip++;n++;
    }
    if(______)*op++='0'+n-1;
    *op++=c;
    if(______)ip++;
    }
    *op='\0';
    return op-outstr;
    }

试题一答案

(1)邻接的顶点
(2)邻接的且未被访问的
(3)未访问过
(4)未被访问过的邻接点的
(5)访问过

[解析] 本题考查连通图的深度优先遍历算法的非递归过程。
在做题前,我们首先来了解一下图的遍历。和树的遍历类似,图的遍历也是从某个顶点出发,沿着某条搜索路径对图中每个顶点各做一次且仅做一次访问。
连通图的深度优先遍历可定义如下:首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点(亦称为从源点可达的顶点)均已被访问为止。其关键是每次遍历都是往下直到最后再往回搜索,找到还未被访问过的邻接点的顶点,然后从该顶点出发,对它及下面的顶点进行深度优先遍历。下面来具体分析其算法。
第1空在第二步中,在访问起始顶点v后应该访问的结点,那么这个结点肯定是与起始顶点v邻接的顶点,因此此空答案为“邻接的顶点”。
第2空是在访问p顶点后应该访问的顶点,接下来应该也是访问与p顶点邻接的顶点,但这个时候p顶点的邻接顶点中有已经被访问过了的顶点,因此在访问前还需判断此顶点是否被访问过了,所以此空答案为“邻接的且未被访问的”。
第3空也在第二步中,结合前后的内容,可以知道此空是要判断是否还可以找到与当前访问顶点邻接而未被访问的顶点,根据上面分析,如果找不到,才往回搜索,因此此空答案为“未访问过”。
第4空是回退过程中要注意的地方,一般回退到还未被访问过的邻接点的顶点,接着访问这个未被访问过的邻接点。因此此空答案为“未被访问过的邻接点的”。
第5空是存放在栈中的内容,栈具有后进先出的特点,根据上面对深度优先遍历的分析可以知道,在回退的过程中需要用到被访问过的顶点,而且回退的过程是按遍历的顶点的顺序回退的,越后被访问的顶点越先被回退,因此此空答案为“访问过”。

试题二答案

(1)*pi=pi
(2)pi<pj或
pi!=*pj
(3)str[i]=del
(4)str[j]
(5)i=j+1

[解析] 本题考查在C语言中对字符串的处理。
[函数1]
使用数组s[n]来存储一个字符串,因为要根据回文字符串的定义来判断一个串是否是回文字符串,所以需要循环比较。
(1)拿该字符串的第一个元素s[0]和最后一个元素s[n-1]比较,如果s[0]不等于s[n-1],则s不是回文字符串。
(2)如果s[0]等于s[n-1],则拿第二个元素s[1]和倒数第二个元素s[n-2]比较,如果s[1]不等于s[n-2],则s不是回文字符串。
(3)依次类推,直到最中间的两个元素也比较完毕(如果s有偶数个元素),或者只剩下中间的一个元素(如果s有奇数个元素)。
当上述循环结束时,如果最中间的元素没有进行比较,就说明s不是回文字符串,如果进行了比较,则s是回文字符串。
在函数1中,pi和pj是两个指向字符的指针,程序首先将s的首地址赋给pi(即pi=a[0]),将元素s[strlen(s)-1]的地址赋给pj(即pj=s[strlen(s)-1]),当pi<pj并且pi和pi所指向的值相等时进行循环:pi自增,pj自减。
退出循环后,如果pi≥pj,则s是回文字符串(如果s有偶数个元素,则为pi>pj;如果s有奇数个元素,则为pi=pj);如果pi<pj,则s不是回文字符串。
[函数2]
由函数2说明可知,此函数对给定的字符串进行从左至右的扫描,找出不包含标志字符的子字符串。
在函数2中,i的初值为0,len表示字符串的长度。当i<len时进行循环:如果当前字符是标志字符,则不做处理,继续扫描。当退出该循环时,当前字符str[i]不是标志字符,这时从str[i]开始寻找,直到找到在标志字符中出现的一个子字符串(i保持不变,用i标记寻找的过程),给找到的字符序列置字符串结束标志,以便于后面语句的输出。
输出语句结束后,就要继续寻找后面的不包含标志字符的子字符串,这时,需要把指针i移动j的后面,继续扫描。

试题三答案

(1)ip-‘0’+1
(2)
++ip
(3)*op++=*ip
(4)*op=‘\0’
(5)n>1
(6)*ip=‘_’

[解析] 本题考查C语言对字符串的处理。
本题对字符串按一定要求进行编码解码,所以编码规则至关重要。在做题前一定要看清规则,并按规则对程序说明中所举的例子进行手动的编码解码工作。必要时,可以将其和程序比较着看。
下面我们来开始分析程序。
int encode(charinstr,charoutstr){
char*ip,op,c;int k,n;
ip=instr;op=outstr;
while(ip){
if(ip>=‘0’&&ip<=‘9’&&(ip+1)){
上面的if条件表明,只有当
ip为数字,且其下一个字符不为空时执行下面的程序段。也就是说,这是编码规则(3)的处理代码。
n=;
c=
;
从下面的循环结合编码规则(3)的“设该数字字符的面值为n,则将它的后继字符(包括后继字符是一个数字字符)重复复制n+1次到新字符串中”,可以看出这里的n应是ip所指数字加1,又因为ip指示的是字符型数据,所以第1空应填“ip-‘0’+1”。c应是ip+1所指示的字符,又因为此段程序中只有一个ip++语句,但这里的操作相当于对两个字符进行了编码,ip要向后跳两个空间,所以第2空应填“++ip”。
for(k=0;k<n;k++)
op++=c;
}
else _____;
这里对应规则(1)和(2)直接把字符拷贝到新串。所以第3空应填“*op++=*ip”。
*op++='
';
ip++;
}
if(op>outstr)op–;
___;
这里应是给新串outstr加上字符串结束符“\0”。因为如果执行了上面的while循环,则会把字符串26a3t2变换结果为666_a_tttt_2,而不是程序说明中的666_a_tttt_2。因为上面的while循环中有“while(…){…*op++='
';ip++;}”。所以要把最后一个“
”用字符串结束符“\0”替换掉,刚好“if(op>outstr)op–;”把op指针定位到了最后的“
”。所以第4空应填“op=‘\0’”。这里要注意一点,“if(op>outstr)op–”不能直接写成op–。因为当输入串instr为空时,outstr也为空,while()不做处理,则op=outstr。这种情况下,直接把\0写到outstr,表示outstr是一个空串。
return op-outstr;
}
接下来我们分析解码程序decode()。
int decode(char
instr,char
outstr){
char
ip,*op,c;int n;
ip=instr;op=outstr;
while(*ip){
c=*ip;n=0;
while(*ipc&&n<10){
ip++;n++;
}
上面的循环用于统计字符c的个数。
if()*op++=‘0’+n-1;
此处把统计个数存到输出串,则表示当前情况符合编码规则(3)。所以第5空应填“n>1”。
*op++=c;
if(
)ip++;
因为解码规则中有“并在复原过程中略过变换函数,为不同组之间添加的一个下划线字符”。所以第6空应填“*ip
’_'”。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值