k++;
其时间复杂度为B。
A.O
(1)B.O(n)C.O(log2n)D.O(n2)
1.下面,对非空线性表特点的论述,C是正确的。
A.所有结点有且只有一个直接前驱
B.所有结点有且只有一个直接后继
C.每个结点至多只有一个直接前驱,至多只有一个直接后继
D.结点间是按照1对多的邻接关系来维系其逻辑关系的
2.一般单链表Lk_h为空的判定条件是A。
A.Lk_h==NULLB.Lk_h->Next==NULL
C.Lk_h->Next==Lk_hD.Lk_h!
=NULL
3.带表头结点的单链表Lk_h为空的判定条件是B。
A.Lk_h==NULLB.Lk_h->Next==NULL
C.Lk_h->Next==Lk_hD.Lk_h!
=NULL
4.往一个顺序表的任一结点前插入一个新数据结点时,平均而言,需要移动B个结点。
A.nB.n/2C.n+1D.(n+1)/2
5.在一个单链表中,已知qtr所指结点是ptr所指结点的直接前驱。
现要在qtr所指结点和ptr所指结点之间插入一个rtr所指的结点,要执行的操作应该是C。
A.rtr->Next=ptr->Next;ptr->Next=rtr;
B.ptr->Next=rtr->Next;
C.qtr->Next=rtr;rtr->Next=ptr;
D.ptr->Next=rtr;rtr->Next=qtr->Next;
1.一个栈的元素进栈序列是a、b、c、d、e,那么下面的C不能做为一个出栈序列。
A.e、d、c、b、aB.d、e、c、b、a
C.d、c、e、a、bD.a、b、c、d、e
2.判定一个顺序队列Qs(最多有n个元素)为空的条件是C。
A.Qs_rear-Qs_front==n*sizeB.Qs_rear-Qs_front+1==n*size
C.Qs_front==Qs_rearD.Qs_front==Qs_rear+size
3.判定一个顺序队列Qs(最多有n个元素)真满的条件是A。
A.Qs_rear-Qs_front==n*sizeB.Qs_rear-Qs_front+1==n*size
C.Qs_front==Qs_rearD.Qs_front==Qs_rear+size
4.在一个链式队列Lq中,Lq_front和Lq_rear分别为队首、队尾指针。
现在由指针ptr所指结点要进队,则插入操作应该是B。
A.Lq_front->Next=ptr;Lq_front=ptr;
B.Lq_rear->Next=ptr;Lq_rear=ptr;
C.ptr->Next=Lq_rear;Lq_rear=ptr;
D.ptr->Next=Lq_front;Lq_front=ptr;
5.链栈与顺序栈相比,一个较为明显的优点是D。
A.通常不会出现栈空的情形B.插入操作更加便利
C.删除操作更加便利D.通常不会出现栈满的情形
6.向链栈插入一个结点时,操作顺序应该是C。
A.先修改栈顶指针,再插入结点B.无须修改栈顶指针
C.先插入结点,再修改栈顶指针D.谁先谁后没有关系
7.从链栈中删除一个结点时,操作顺序应该是A。
A.先保存被删结点的值,再修改栈顶指针
B.先修改栈顶指针,再保存被删结点的值
C.无须修改栈顶指针的值
D.谁先谁后没有关系
8.一个循环队列的最大容量为m+1,front为队首指针,rear为队尾指针。
那么进队操作时求队位号应该使用公式D。
A.Cq_front=(Cq_front+1)%mB.Cq_front=(Cq_front+1)%(m+1)
C.Cq_rear=(Cq_rear+1)%mD.Cq_rear=(Cq_rear+1)%(m+1)
9.在一个循环顺序队列里,队首指针Cq_front总是指向B。
A.队首元素B.队首元素的前一个队位
C.任意位置D.队首元素的后一个队位
10.若一个栈的进栈序列是1、2、3、4,那么要求出栈序列为3、2、1、4时,进、出栈操作的顺序应该是A。
(注:
所给顺序中,I表示进栈操作,O表示出栈操作)
A.IIIOOOIOB.IOIOIOIOC.IIOOIOIOD.IOIIIOOO
4.设有一个8阶的对称矩阵A,采用以行优先的方式压缩存储。
a11为第1个元素,其存储地址为1,每个元素占一个地址空间。
试问元素a85的地址是A。
A.33B.30C.13D.23
5.一个m*m的对称矩阵,如果以行优先的方式压缩存入内存。
那么所需存储区的容量应该是C。
A.m*(m-1)/2B.m*m/2C.m*(m+1)/2D.(m+1)*(m+1)/2
7.二维数组M中的每个元素占用3个存储单元,行下标i从1变到8,列下标j从1变到10。
现从首地址为SA的存储区开始存放A。
那么该数组以行优先存放时,元素A[8][5]的起始地址应该是C。
A.SA+141B.SA+180C.SA+222D.SA+225
8.设有一个5阶上三角矩阵A,将其元素按列优先顺序存放在一维数组B中。
已知每个元素占用2个存储单元,B[1]的地址是100。
那么A[3][4]的地址是A。
A.116B.118C.120D.122
6.在一棵非空二叉树的中序遍历序列里,根结点的右边D结点。
A.只有左子树上的部分B.只有左子树上的所有
C.只有右子树上的部分D.只有右子树上的所有
8.权值为1、2、6、8的四个结点,所构造的哈夫曼树的带权路径长度是D。
A.18B.28C.19D.29
9.一棵二叉树度2的结点数为7,度1的结点数为6。
那么它的叶结点数是C。
A.6B.7C.8D.9
10.在一棵二叉树中,第5层上的结点数最多是C个。
A.8B.15C.16D.32
1.已知一棵单右支的二叉树,如下左图所示。
把它还原成森林,应该是D。
A.
B.
C.
D.
2.将一棵树Tr转换成相应的二叉树Bt,那么对Tr的先序遍历是对Bt的A。
A.先序遍历B.中序遍历C.后序遍历D.无法确定
3.将一棵树Tr转换成相应的二叉树Bt,那么对Tr的后序遍历是对Bt的B。
A.先序遍历B.中序遍历C.后序遍历D.无法确定
4.设森林F中有3棵树,依次有结点n1、n2、n3个。
把该森林转换成对应的二叉树后,该二叉树的右子树上的结点个数是D。
A.n1B.n1+n2C.n3D.n2+n3
5.设有由三棵树T1、T2、T3组成的森林,其结点个数分别为n1、n2、n3。
与该森林相应的二叉树为Bt。
则该二叉树根结点的左子树中应该有结点A个。
A.n1-1B.n1C.n1+1D.n1+n2
6.现有一棵度为3的树,它有两个度为3的结点,一个度为2的结点,两个度为1的结点。
那么其度为0的结点的个数应该是C。
A.5B.8C.6D.9
注意:
有n个结点的树,树中所有结点的度之和为n-1。
现在这棵树应该满足条件:
n-1=2*3+1*2+2*1=10
这表示该树共有11个结点(加上一个根结点)。
在11个结点里,减去度为3、2、1的结点数5,剩下的就是度为0的结点。
所以,该树有叶结点6个。
7.一棵有n个结点的树,在把它转换成对应的二叉树之后,该二叉树根结点的左子树上共有B个结点。
A.n-2B.n-1C.n+1D.n+2
8.一棵有n个结点的树,在把它转换成对应的二叉树之后,该二叉树根结点的右子树上共有A个结点。
A.0B.nC.n+1D.n+2
1.在一个有n个顶点的无向图中,要连通全部顶点,至少需要C条边。
A.nB.n+1C.n-1D.n/2
2.对于一个无向完全图来说,它的每个不同顶点对之间,都存在有一条边。
因此,有n个顶点的无向完全图包含有C条边。
A.n(n-1)B.n(n+1)C.n(n-1)/2D.n(n+1)/2
3.对于一个有向完全图来说,它的每个不同顶点对之间,都存在有两条弧。
因此,有n个顶点的有向完全图包含有A条边。
A.n(n-1)B.n(n+1)C.n(n-1)/2D.n(n+1)/2
4.在一个无向图中,所有顶点的度数之和,是其所有边数之和的C倍。
A.1/2B.1C.2D.4
5.在一个有向图中,所有顶点的入度之和B所有顶点的出度之和。
A.二分之一于B.等于C.两倍于D.四倍于
6.一个无向连通网图的最小生成树A。
A.有一棵或多棵B.只有一棵C.一定有多棵D.可能不存在
7.一个无向图有n个顶点,那么该图拥有的边数至少是D。
A.2nB.nC.n/2D.0
8.一个有n个顶点的无向连通网图,其生成树里含有C条边。
A.4n-1B.2n-1C.n-1D.n/2
三、问答题(4分/题,共5题)
1.在一个单链表中,为了删除指针ptr所指的结点,有人编写了下面的操作序列。
读懂并加以理解。
试问,编写者能够达到目的吗?
其思想是什么?
x=ptr->Data;
qtr=ptr->Next;
ptr->Data=ptr->Next->Data;
ptr->Next=ptr->Next->Next;
free(qtr);
答:
能够达到删除指针ptr所指结点的目的。
编写者的思想是不去直接删除ptr所指的结点,而是在把ptr直接后继的Data域内容写入ptr所指结点的Data域之后,把它的直接后继删除。
对于单链表来说,得到一个结点的直接后继容易,得到它的直接前驱难,所以这样的设计是有其可取之处的。
2.在一个单链表中,为了在指针ptr所指结点之前插入一个由指针qtr所指的结点,有人编写了下面的操作序列,其中temp是一个临时工作单元。
读懂并加以理解。
试问,编写者能够达到目的吗?
其思想是什么?
qtr->Next=ptr->Next;
ptr->Next=qtr;
temp=ptr->Data;
p->Data=qtr->Data;
qtr->Data=temp;
答:
能够达到在指针ptr所指结点之前插入一个由指针qtr所指结点的目的。
编写者的思想是考虑到在单链表中得到一个结点的前驱信息较为困难,因此在这里先把qtr所指结点插入到ptr所指结点的后面,暂时成为它的直接后继。
然后通过临时工作单元temp,将ptr及qtr所指结点的Data域内容进行交换,从而达到插入的目的。
4.设有6个元素a1、a2、a3、a4、a5、a6,它们以此顺序依次进栈。
假定要求它们的出栈顺序是a4、a3、a2、a6、a5、a1,那么应该如何安排push和pop操作序列?
答:
所需的push和pop操作序列如下:
push,push,push,push,pop,pop,pop,push,push,pop,pop,pop
5.有中缀表达式a/(b/(c/(d/e)))。
有人将其转化为相应的后缀表达式是abcde////。
这一转化结果对吗?
答:
转化结果是对的。
7.分别写出如图5-32所示二叉树的先序、中序、后序遍历序列。
图5-32二叉树示例
答:
先序遍历序列为:
A-B-C-D-F-G-H-E,中序遍历序列为:
B-A-D-G-F-H-C-E,后序遍历序列为:
B-G-H-F-D-E-C-A。
3.有如图7-23所示的一个无向图,给出它的邻接矩阵以及从顶点v1出发的深度优先遍历序列。
答:
它的邻接矩阵如图所示。
从顶点v1出发的深度优先遍历序列为:
v1->v2->v4->v5->v7->v6->v3
注意,该序列是不唯一的。
四、应用题(6分/题,共5题)
3.分析算法段中标有记号“#1”和“#2”的基本操作的执行次数:
for(i=0;ifor(j=0;j{
#1y=1;
for(k=0;k#2y=y+1;
}
答:
标有记号“#1”的基本操作的执行次数是:
n2;标有记号“#2”的基本操作的执行次数是:
n3。
4.给出下面3个算法段的时间复杂度:
(1)x++;
(2)for(j=1;jx++;
(3)for(j=1;j<=n;j++)
{
printf(“j=%”,j);
for(k=j;k<=n;k++)
x++;
}
答:
(1)的时间复杂度为O
(1);
(2)的时间复杂度O(n);
(3)中“printf(“j=%”,j);”执行次数的数量级为O(n),“x++;”执行次数是:
n+(n-1)+(n-2)+……+2+1=n(n+1)/2
其数量级为O(n2),因此整个算法段的时间复杂度应该是O(n2)。
4.试设计一个算法copy(Ck_h1,Ck_h2),将一个带表头结点的、以Ck_h1为表头指针的单链表Ck1的内容,复制到一个不带表头结点的、以Ck_h2为表头指针的单链表Ck2中。
答:
算法具体如下。
Copy(Ck_h1,Ck_h2)
{
ptr=Ck_h1->Next;
qtr=Ck_h2;
while(ptr!
=NULL)
{
rtr=malloc(size);
rtr->Data=ptr->Data;
qtr->Next=rtr;
qtr=rtr;
ptr=ptr->Next;
}
qtr->Next=NULL;
}
5.已知一个带表头结点的递增单链表。
试编写一个算法,功能是从表中去除值大于min、且值小于max的数据元素。
(假定表中存在这样的元素)
答:
所需算法编写如下。
Del_Sq(Lk_h,min,max)
{
ptr=Lk_h->Next;/*ptr指向链表的起始结点*/
while((ptr!
=NULL)&&(ptr->Data<=min))/*跳过所有值<=min的结点*/
{
qtr=ptr;
ptr=ptr->Next;
}
while((ptr!
=NULL)&&(ptr->Datap=p->Next;
qtr->Next=ptr;/*qtr指出第1个大于max的结点位置,完成链接*/
}
6.已知一个带表头结点的无序单链表。
试编写一个算法,功能是从表中去除所有值大于min、且值小于max的数据元素。
答:
所需算法编写如下,其中指针ptr总是指向当前被检查的结点,qtr总是指向被检查结点的直接前驱。
Del_Lk(Lk_h,min,max)
{
ptr=Lk_h->Next;/*ptr指向单链表的起始结点*/
while(ptr!
=NULL)/*扫视直到链尾结点*/
{
if((ptr->Data<=min)||(ptr->Data>=max)/*不满足删除条件*/
{
qtr=ptr;/*往后移动qtr和ptr*/
ptr=ptr->Next;
}
else/*删除ptr所指结点,往后移动ptr*/
{
qtr->Next=ptr->Next;
free(ptr);
ptr=qtr->Next;
}
}
}
7.一个单链表Lk的表头指针为Lk_h,不同结点的Data域值有可能相同。
编写一个算法,功能是计算出Data域值为x的结点的个数。
答:
算法应该遍历链表的每一个结点,遇到一个结点的Data域值为x时,计数器n就加1。
最后返回计数器n。
Count_Lk(Lk_h)
{
n=0;
ptr=Lk_h;
while(ptr!
=NULL)
{
if(ptr->Data==x)
n=n+1;
ptr=ptr->Next
}
return(n);
}
3.编写一个算法,它能够取得链式队列首元素的值。
答:
取得链式队列首元素的值,只有在队列非空的前途下才有意义。
算法编写如下。
Getf_Lq(Lq_front,Lq_rear)
{
if(Lq_front==Lq_rear)/*队列空!
*/
printf(“Thelinkedqueueisempty!
”);
else/*队列非空!
*/
{
ptr=Lq_front->Next;
x=ptr->Data;
return(x);
}
}
5.将中缀表达式转化为后缀表达式的方法类似于中缀表达式求值。
具体地,要开辟一个运算符栈op和一个数组st。
在自左至右扫描算术表达式时,遇到操作数就直接顺序存入st;遇到运算符时就与op栈顶元素比较,高则进栈,不高则让栈顶元素出栈,存入st,然后该运算符再次去与新的op栈顶元素比较。
最后,在数组st里形成所需要的后缀表达式。
试用这种方法,用图示将中缀表达式5+8*3-2转化成为相应的后缀表达式。
答:
相应的后缀表达式是583*+2-,其图示如下。
4.编写一个算法,将顺序串St中所有的大写字母全部换成小写字母。
(提示:
大写英文字母A~Z对应的ASCII码为65~90,小写英文字母a~z对应的ASCII码为97~122,在大写字母的ASCII码上加32,就是对应小写字母的ASCII码)
答:
算法编写如下。
Catosm_St(St)
{
for(i=1;i<=St_len;i++)
if((A<=St[i])&&(St[i]<=Z))
St[i]=St[i]+32;
}
8.已知两个mⅹn的矩阵A和B。
编写一个算法,求C=A+B。
即C也是一个mⅹn的矩阵,其元素满足条件:
cij=aij+bij(1≤i≤m,1≤j≤n)
答:
算法名为Add_Mt(),参数为A,B,C。
Add_Mt(A,B,C)
{
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
C[i][j]=A[i][j]+B[i][j];
}
2.已知中序遍历序列为:
A-B-C-E-F-G-H-D,后序遍历序列为:
A-B-F-H-G-E-D-C。
试画出这棵二叉树。
答:
这棵二叉树如应用题2答案图所示。
6.权值序列为:
10、16、20、6、30、24,请用图示来表达构造一棵哈夫曼树的全过程。
答:
构造这棵哈夫曼树的全过程如下所示。
3.将图6-26所示的二叉树转换成相应的森林。
图6-26二叉树示例图6-27树示例
答:
转换成的森林如下图所示。
4.给出如图6-27所示树的先序遍历序列和后序遍历序列。
答:
该树的先序遍历序列为:
A-B-E-F-K-L-M-C-G-D-H-I-J;该树的后序遍历序列是:
E-K-M-L-F-B-G-C-H-I-J-D-A。
5.将图6-28所示的森林转换成对应的二叉树。
图6-28森林示例图6-29树示例
答:
对应的二叉树如下图所示。
6.将图6-29所示的树转换成相对应的二叉树。
答:
对应的二叉树如下图所示
1.利用Kruskal算法,求下图所给无向连通网图的最小生成树。
答:
初始时,所求MST里只有七个各自孤立的连通分量,如图(a)所示。
开始执行Kruskal算法时,从图的边E里挑选边(v6,v7),因为这两个顶点分属MST中的不同连通分量,且权值为最小。
这样,该边把MST里的顶点v6和v7连接在了一起,如图(b)所示。
接着,从图的边E里挑选边(v1,v3)、挑选边(v1,v2)、挑选边(v4,v6)挑选边(v5,v7)挑选边(v3,v6),最终得到如图(g)所示的最小生成树。
2.利用Floyd算法,求图7-25所示的有向网图中各顶点对的最短路径长度。
图7-25有向网图示例
答:
Floyd算法基于的邻接矩阵,以及推演出的各个矩阵、最终结果如下所示。
3.利用Dijkstra算法,求左图所示的图中顶点v1到其他各顶点间的最短路径长度。
答:
v1到v2的最短路径长度是4;v1到v3的最短路径长度是4;v1到v4的最短路径长度是1;v1到v5的最短路径长度是6;v1到v6的最短路径长度是3;v1到v7的最短路径长度是6;v1到v8的最短路径长度是7。
如右