【PTA】【878真题】浙江大学软件学院878自命题2016真题

说明:

  • 题目来自PTA平台的C语言与数据结构考研模拟卷(1)
  • 部分题目没答案是因为博主也做错了,不知道正确答案
  • 如果有不会做的题目或者知道正确答案,可以评论或者私信我,谢谢

选择题

2-1

若有以下说明和定义

typedef int  *INTEGER;
INTEGER a,*b;

那么以下叙述正确的是:

选项
Aa 是 int 型的指针变量
Bb 是 int 型的一级指针变量
Ca 是 int 型变量
D程序中可用 INTEGER 代替 int 类型名

解析:a 是 int 型的指针变量,b 是 int 型的二级指针变量。

2-2

下列程序段的输出结果是:

int k=2, s=0;
switch(k) {
    case 2: s++; k++;
    case 1: s++;
    case 3: s+=1;
         switch(s){
            case 2: s+=2; break;
            default: k++; break;
         }
    default: s+=3;
}
printf("%d#%d#", s, k);
选项
A1#3#
B 6#4#
C3#2#
D3#4#

2-3

执行语句:for(i=1;i++<4;);后变量 i 的值是:

选项
A3
B4
C5
D不定

2-4

ks的当前值分别为 4、0,执行语句 while(k--)s+=k; ks值分别为:

选项
A0、10
B-1、10
C0、6
D-1、6

解析:当第四轮循环开始时,k为0,循环结束,k-1=-1,s=3+2+1+0=6。

2-5

编译运行下列程序的输出结果是:

void fun(int a, int b, int c)
{  c =a*b;
}

int main( )
{   int c;
    fun(4,3,c);
    printf("%d",c);
    return 0;
}
选项
A0
B12
C编译错误
D无法确定

解析:由于函数并未改变c的值,所以c为初始值,然而c为局部变量且没有赋初值,故无法确定。

2-6

输入 ABCDEFG时,下列程序的输出结果是:

int f(char s[])
{   if(*s == '\0') return 0;
    else  return 1+f(s+1);
}

int main()
{   char s[10];
    gets(s);
    printf("%d",f(s)/2 );
    return 0;
}
选项
A0
B 3
C4
D7

2-7

下列程序的输出结果是:

# include <stdio.h>
int x=1;

int f(int x)
{   static int k=0;
    return (k++) + x;
}

int main()
{   int k;
    for(k=1; k<4; k++)
          printf("%d#", f(k+x));
}
选项
A3#4#5#
B2#3#4#
C2#4#6#
D3#5#7#

解析:k为静态变量,重新赋值不改变当前的值;f函数中先返回k+x的值,然后执行k++。

2-8

如果有宏定义 #define MUL(x,y) (x*y);那么表达式 MUL(MUL(2+3,6),4+2)-7的值是:

选项
A173
B 75
C113
D69

解析:注意替换的时候不要忘记外层的括号。

2-9

已知 ‘9’ 的 ASCII 码是 57,‘a’ 的 ASCII 码是 97,‘A’ 的 ASCII 码是 65。

以下程序结果是:

int main()
{   char a[40]="a\065\0b";
    puts(a);
    return 0;
}
选项
AaA
Ba\065\0b
Ca5
Da

解析:输出为a5,a\065\0b中\065为5的ASCII码的八进制,后面的\0为结束符号。

2-10(暂时未知正确答案,只知道C是错的)

设有如下函数,期望返回一个字符串:

char *p(int n)
{   ______________________________
    return s+n;
}

该函数内的下划线处填入以下哪个选项时,将不能正确得到函数返回的字符串?

选项
Achar *s=“abcdefghij”;
Bchar s[]=“abcdefghij”;
Cstatic char s[]=“abcdefghij”;
Dchar *s; s=(char *)malloc(10); strcpy(s,“abc123”);

解析:。

2-11

若有以下程序段:

struct dent {
    int no;
    int *m;
};
int a = 1, b = 2, c = 3;
struct dent s[3] = {{101, &a}, {102, &b}, {103, &c}};

int main()
{   struct dent *p = s;
    ……
}

则以下表达式中值为 2 的是:

选项
A((p+1))->m
B*(p++)->m
C(*p).m+1
D*(++p)->m

解析:A选项为2的地址,B选项为1,C选项为1的地址+1,D选项为正确选项。

2-12(暂时未知正确答案,只知道A是错的)

如果有变量定义 char **pp[10];,那么下面说法正确的是:

选项
App 是指向字符指针的指针变量
Bpp 是字符指针
Cpp[4] 是字符指针
Dpp 是数组名

解析:。

2-13

设有以下语句,则变量 c的十进制数是:

char  a = 3, b = 6, c;
c = a^b<<4-2;
选项
A27
B20
C78
D97

解析:优先级:减号 > 左移号 > 异或,2^(3<<2)=27。

2-14

运行下列程序,得到文件的内容是:

void fun(char *fname, char *st)
{   FILE *myfile; int i;
    myfile = fopen(fname,"w" );
    for(i=0; i<strlen; i++)
        fputc(st[i], myfile);
    fclose(myfile);
}

int main()
{   fun("f_", "Programming_");
    fun("f_", "in_C_is_fun");
    return 0;
}
选项
AProgramming_in_C_is_fun
B in_C_is_fun
Cf_in_C_is_fun
Din_C_is_fun_

解析:w 打开只写文件,若文件存在则文件长度清为0,故文件中只有第二个字符串。

2-15

运行该程序的输出结果是:

#include <stdio.h>
int main()
{   int x=5, y=3, z=1;
    printf("%d %d\n",(++x,y++),z+1);
    return 0;
}
选项
A6 4
B6 3
C4 2
D3 2

解析:逗号表达式取后面的一项y++,故最后输出的是3。

2-16(暂时未知正确答案,只知道C是错的)

以下给出四种算法的时间复杂度,如果当 N=100 时它们对应的运行时间依次是:A 算法 100 毫秒、B 算法 30 毫秒、C 算法 20 毫秒、D 算法 10 毫秒,则当 N=200 时,哪种算法最快?

选项
A O ( N ) O(N) O(N)
B O ( N 2 ) O(N^2) O(N2)
C O ( N 3 ) O(N^3) O(N3)
D O ( N 4 ) O(N^4) O(N4)

2-17(暂时未知正确答案,只知道D是错的)

对于顺序存储和链式存储的长度为 N 的线性表,访问结点的时间复杂度分别为:

选项
A O ( 1 ) 和 O ( 1 ) O(1)和O(1) O(1)O(1)
B O ( 1 ) 和 O ( N ) O(1)和O(N) O(1)O(N)
C O ( N ) 和 O ( 1 ) O(N)和O(1) O(N)O(1)
D O ( N ) 和 O ( N ) O(N)和O(N) O(N)O(N)

2-18

有五个元素以 2、4、5、1、3 的顺序进栈 S,每个出栈元素都必须立刻进入队列 Q,问哪个不是合法的出队列 Q 的序列?

选项
A2 4 5 1 3
B3 1 5 4 2
C1 3 5 2 4
D1 5 3 4 2

2-19

18 叉树中只有 5 个度为 3 的结点、2 个度为 18 的结点和若干叶结点,则叶结点个数是:

选项
A45
B51
C52
D无法确定

2-20

某非空二叉树的先序遍历和中序遍历序列相同,则该树的形态是:

选项
A只有一个根结点
B没有度为 1 的结点
C所有结点只有左孩子
D所有结点只有右孩子

2-21

我们记 L 为对左子树的递归访问,R 为对右子树的递归访问,T 为对根结点的访问。则对二叉搜索树进行什么遍历可以得到从大到小的有序序列?

选项
ARTL
BLTR
CRLT
DTLR

2-22

将 26, 13, 44, 51, 98, 37, 58, 66 顺序插入一棵初始为空的 AVL 树。下列句子中哪句是错的?

选项
A44 是根结点
B51 和 98 是兄弟
C26 是 37 的父结点
D37 和 66 是兄弟

2-23

设最大堆的层序遍历结果为 { 95, 72, 86, 50, 65, 12, 23, 42 }。用线性时间复杂度的算法将该堆调整为最小堆。则该树的中序遍历结果为:

选项
A95, 65, 42, 72, 12, 86, 23, 50
B12, 42, 23, 65, 72, 86, 50, 95
C12, 42, 23, 50, 65, 86, 95, 72
D72, 50, 42, 65, 12, 86, 23, 95

2-24

由分别带权为 7、2、3、5 的四个叶子结点构成一棵哈夫曼树,该树的带权路径长度为?

选项
A17
B22
C32
D34

2-25

对于有向图,其邻接表表示比邻接矩阵表示更易于:

选项
A求一个顶点的出边邻接点
B求一个顶点的入度
C进行图的深度优先遍历
D进行图的广度优先遍历

2-26(暂时未知正确答案,只知道B是错的)

对于一个具有 N 个顶点的无向图,要连通所有顶点至少需要多少条边?

选项
AN-1
BN
CN+1
DN/2

2-27

对于给定的有向图如右图,其强连通分量为:
在这里插入图片描述

选项
A{1,2} {3,4,5}
B{1} {2,4,5} {3}
C{1,2,4} {3} {5}
D{1,3,4} {2,5}

2-28

设一棵非空完全二叉树 T 的所有叶节点均位于同一层,且每个非叶结点都有 2 个子结点。若 T 有 1024 个叶结点,则 T 的结点总数是:

选项
A2047
B2048
C2049
D1048576

2-29

已知二叉搜索树如右图所示,则元素之间不应满足的大小关系是:

选项
AB<C<A
BB<D<C
CD<B<A
DD<C<A

2-30

在一个有权无向图中,如果顶点 b 到顶点 a 的最短路径长度是 13,顶点 c 与顶点 a 之间存在一条长度为 3 的边。那么下列说法中哪句是正确的?

选项
Ac 到 b 的最短路径长度就是 16
Bc 到 a 的最短路径长度就是 3
Cc 到 b 的最短路径长度不小于 10
Dc 到 b 的最短路径长度与 b 到 a 的最短路径长度无关

2-31

设无向图为 G=(V,E),其中 V={v1,v2,v3,v4},E={(v1,v2),(v3,v4),(v4,v1),(v2,v3),(v2,v4)}。则每个顶点的度依次为:

选项
A2, 1, 1, 1
B1, 1, 2, 1
C3, 2, 3, 2
D2, 3, 2, 3

2-32

在下列查找的方法中,平均查找长度与结点个数无关的查找方法是:

选项
A顺序查找
B二分法
C利用散列表
D利用二叉搜索树

2-33

已知线性表的关键字集合 { 21,11, 13,25,48,6,39,83,30,96,108 },散列函数为 h=key%11,采用分离链接法解决冲突。则成功查找的平均查找长度为:

选项
A1.18
B1.27
C1.36
D2.36

2-34

输入 1 0 6 10^6 106 个只有一位数字的整数,可以用 O(N) 复杂度将其排序的算法是:

选项
A快速排序
B桶排序
C堆排序
D希尔排序

2-35

采用递归方式对顺序表进行快速排序,下列关于递归次数的叙述中,正确的是:

选项
A递归次数与每次划分后得到的分区处理顺序无关
B递归次数与初始数据的排列次序无关
C每次划分后,先处理较长的分区可以减少递归次数
D每次划分后,先处理较短的分区可以减少递归次数

填空题

4-1

下列程序运行输出结果为:5

#include <stdio.h>
int ack(int m, int n); 
int main() 
{   int m=2, n=1; 
    printf("%d", ack(m,n)); 
    return 0; 
} 
int ack(int m, int n) 
{   if (m == 0) return n+1; 
    if (n == 0) return ack(m-1, 1); 
    return ack(m-1, ack(m, n-1)); 
}

4-2

下列程序段的输出结果是:28

int i, j, k, count=0;
for(i=0; i<8; i++)
    for(j=0; j<i; j++)
        if (j%2) 
            for(k=0; k<j; k++)  count++;
        else 
            continue;
printf("%d",count);

4-3

假如下面程序的源程序文件名是 echo.c,编译链接后的可执行程序文件名是 echo.exe,那么执行命令 echo How Are You?的输出是:Good!

#include <stdio.h>
int main(int argc, char *argv[])
{   int k, i=0;
    static char s[10]= "Good!";
    for(k = 1; k <argc; k++)  s[i++] = *(argv[k]+k);
    printf("%s", s);     
    return 0;
}

4-4

给定一棵树的先序遍历序列为 { 1 2 3 4 6 7 5 },后序遍历序列为 { 2 6 7 4 5 3 1 }。
(1)请描述这棵二叉树:

  • 根结点是 1
  • 3 是根结点的右孩子
  • 4 和 5是兄弟结点
  • 树中共有 4 个叶结点

(2)请写出该树的中序遍历结果。

2
1
6
4
7
3
5

4-5

给定无向带权图如图所示:
在这里插入图片描述
(1) 请给出从顶点 a 出发深度优先搜索遍历该图的顶点序列(多个顶点可以选择时按字母序):
a b c e d f g h
(2) 请给出从顶点g出发广度优先搜索遍历该图的顶点序列(多个顶点可以选择时按字母序):
g d e h f b c a
(3) 请描述最小生成树:
该树的权重是 31 ;树中(填 从 e 到 g 的这条边。

程序填空题

5-1 选猴王

一群猴子要选新猴王。新猴王的选择方法是:让 n只候选猴子围成一圈,从某位置起顺序编号为 1~n号。从第 1 号开始报数(从 1 到 4),凡报到 4 的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。以下程序采用单循环链表模拟了这个过程,KingOfMonkey函数返回猴王编号。请在空缺处填上正确的代码。

typedef struct node    
{   int number; /*猴子的编号*/
    struct node *next; /*指向下一只猴子的指针*/
} linklist;
int steps = 4; /*报数到这个定数(正整数),确定下一只出局的猴子*/
linklist *CreateCircle(int n); /*创建有n个编号的无头结点单循环链表*/
int KingOfMonkey(int n, linklist *head);
int main()
{   linklist *head;
    int n;
    scanf("%d",&n); 
    if (n>0){    
        head = CreateCircle(n);
        printf("%d\n", KingOfMonkey(n,head));
    }
    return 0;
}

linklist *DeleteNext(linklist *p) /* 删除单循环链表的p所指的下一个结点 */
{   linklist   *s;
    if ( p && p->next!=p ) { 
        s=p->next;  //填空处
        p->next = s->next;
        free(s);  return p->next;
    }else if (p){             
        free(p);  return NULL;
    }else return NULL;
}

int KingOfMonkey(int n,linklist *head)
{   linklist *p = head;
    int i, j;       
    for(j=1; j<=n-1; j++){   
        for(i=2; i<steps; i++)  p=p->next;
        p=DeleteNext(p); //填空处
    }   
    return p->number; //填空处
} 

5-2 有理数相加

假如有理数类型定义如下:

typedef struct
{   int n; /*numerator,分子,允许是负数*/
    int d; /*denominator,分母,大于0;且n和d没有大于1的公因子*/
} RATIONAL;

下面是两个有理数的加法函数 AddR()以及相关的另两个函数代码,请对程序填空。

unsigned int gcd( int x, int y); /*求最大公因子*/
RATIONAL Simplify(RATIONAL a); /*有理数约简,如6/9约简为2/3*/
RATIONAL AddR(RATIONAL a, RATIONAL b) /*有理数相加,如:1/2+2/3=7/6 */
{   RATIONAL t;
    a = Simplify(a); b = Simplify(b);
    t.n = a.n*b.d+a.d*b.n; //填空处
    t.d = a.d * b.d;
    return Simplify(t);
}
RATIONAL Simplify(RATIONAL a) /*化简有理数*/
{   RATIONAL t;
    int divisor = gcd(a.n,a.d); //填空处
    t.n =  a.n / divisor;
    t.d = a.d / divisor;
    return t;
}
unsigned int gcd(int x, int y) /*y>0; 求|x|与y的最大公因子*/
{   int r;
    if ( x < 0 ) x = -x;
    while(1)
    {   r = x % y;
        if (r == 0) return y;
        x = y;
        y=r; //填空处
    }
}

5-3 拓扑排序(暂时未知正确答案)

下列代码的功能是对一个给定的图G执行拓扑排序,其中TopNum[]从 1 开始记录拓扑序。请完成程序填空。

void Topsort( Graph G )
{   Queue Q;
    Vertex V, W;
    NodePtr ptr;
    int counter = 0;
    Q = CreateEmptyQueue(G->NumV); /*初始化队列*/
    for ( V=0; V<G->NumV; V++ )
        if ( Indegree[V] == 0 ) /*Indegree[V]记录V的入度*/
            Enqueue(V, Q);
    while ( !IsEmpty(Q) ){
        V = Dequeue( Q );
        TopNum[V] = ;  //填空处
        for ( ptr=G->List[V]; ptr; ptr=ptr->Next) {
            W = ptr->Vert;
            if () //填空处
                Enqueue(W, Q);
        }
    }
    if () //填空处
        printf("错误:此图存在环\n");
    DisposeQueue(Q);
}

函数题

6-1 有序链表的并集与去重(暂时未知正确答案)

给定两个带头结点的严格降序的链表 L1L2,要求你求两个链表的并集,其中元素仍然严格降序排列,且必须排除重复元素;重复的元素必须链成另一个降序排列的链表。完成去重合并后,并集链表的表头为 L1,重复元素链表的表头为 L2。

例如:L1→头结点→13→10→9→5;L2→头结点→15→10→5→2。

则合并后:L1→头结点→15→13→10→9→5→2;L2→头结点→10→5。

函数接口定义:
void ListUnion( List L1, List L2 )

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    int Key;
    PtrToNode Next;
};
typedef PtrToNode List;

要求算法额外空间复杂度为O(1),时间复杂度为O(n)。

裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>

typedef struct Node *PtrToNode;
struct Node {
    int Key;
    PtrToNode Next;
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表;空链表将输出NULL */

void ListUnion( List L1, List L2 );

int main()
{
    List L1, L2;
    L1 = Read();
    L2 = Read();
    ListUnion(L1, L2);
    Print(L1);
    Print(L2);
    return 0;
}

/* 你的代码将被嵌在这里 */
输入样例:
4
13 10 9 5
4
15 10 5 2
输出样例:
15 13 10 9 5 2
10 5
参考答案:

在这里插入图片描述
来自 @h70208879 大佬的解析,很详细。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值