s+=B[i][j];
sum=s;
答:
O(n^2)
4.下面程序段的时间复杂度是_______。
i=1;
While(i<=n)
i=i*3;
答:
log3n
第二章线性表
一、判断题
1.线性表的逻辑顺序与存储顺序总是一致的。
(ERROR)
2.顺序存储的线性表可以按序号随机存取。
(OK)
3.顺序表的插入和删除一个数据元素,因为每次操作平均只有近一半的元素需要移动。
(OK)
4.线性表中的元素可以是各种各样的,但同一线性表中的数据元素具有相同的特性,因此是属于同一数据对象。
(OK)
5.在线性表的顺序存储结构中,逻辑上相邻的两个元素在物理位置上并不一定紧邻。
(ERROR)
6.在线性表的链式存储结构中,逻辑上相邻的元素在物理位置上不一定相邻。
(OK)
7.线性表的链式存储结构优于顺序存储结构。
(ERROR)
8.在线性表的顺序存储结构中,插入和删除时,移动元素的个数与该元素的位置有关。
(OK)
9.线性表的链式存储结构是用一组任意的存储单元来存储线性表中数据元素的。
(OK)
10.在单链表中,要取得某个元素,只要知道该元素的指针即可,因此,单链表是随机存取的存储结构。
(ERROR)
二、单选题、(请从下列A,B,C,D选项中选择一项)
11.线性表是(A)。
(A)一个有限序列,可以为空;(B)一个有限序列,不能为空;
(C)一个无限序列,可以为空;(D)一个无序序列,不能为空。
12.对顺序存储的线性表,设其长度为n,在任何位置上插入或删除操作都是等概率的。
插入一个元素时平均要移动表中的(A)个元素。
(A)n/2(B)(n+1)/2(C)(n–1)/2(D)n
13.线性表采用链式存储时,其地址(D)。
(A)必须是连续的;(B)部分地址必须是连续的;
(C)一定是不连续的;(D)连续与否均可以。
14.用链表表示线性表的优点是(C)。
(A)便于随机存取
(B)花费的存储空间较顺序存储少
(C)便于插入和删除
(D)数据元素的物理顺序与逻辑顺序相同
15.某链表中最常用的操作是在最后一个元素之后插入一个元素和删除最后一个元素,则采用(D)存储方式最节省运算时间。
(A)单链表
(B)双链表
(C)单循环链表
(D)带头结点的双循环链表
16.循环链表的主要优点是(D)。
(A)不再需要头指针了
(B)已知某个结点的位置后,能够容易找到他的直接前趋
(C)在进行插入、删除运算时,能更好的保证链表不断开
(D)从表中的任意结点出发都能扫描到整个链表
17.下面关于线性表的叙述错误的是(B)。
(A)线性表采用顺序存储,必须占用一片地址连续的单元;
(B)线性表采用顺序存储,便于进行插入和删除操作;
(C)线性表采用链式存储,不必占用一片地址连续的单元;
(D)线性表采用链式存储,便于进行插入和删除操作;
18.单链表中,增加一个头结点的目的是为了(C)。
(A)使单链表至少有一个结点(B)标识表结点中首结点的位置
(C)方便运算的实现(D)说明单链表是线性表的链式存储
19.若某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用(D)存储方式最节省运算时间。
(A)单链表(B)仅有头指针的单循环链表
(C)双链表(D)仅有尾指针的单循环链表
20.若某线性表中最常用的操作是取第i个元素和找第i个元素的前趋元素,则采用()存储方式最节省运算时间(B)。
(A)单链表(B)顺序表
(C)双链表(D)单循环链表
21.一个向量(一种顺序表)第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是_______。
A.110B.108
C.100D.120
答:
B
[第5个元素的地址=100+2*(5-1)=108]
22.不带头结点的单链表head为空的判定条件是______。
A.head==NULL;B.head->next==NULL;
C.head->next==head;D.head!
=NULL;
答:
A
23.带头结点的单链表head为空的判定条件是______。
A.head==NULL;B.head->next==NULL;
C.head->next==head;D.head!
=NULL;
答:
B
24.在循环双链表的p所指结点之后插入s所指结点的操作是_____。
A.p->right=s;s->left=p;p->right->left=s;s=->right=p->right;
B.p->right=s;p->right->left=s;s->left=p;s->right=p->right;
C.s->left=p;s->right=p->right;p->right=s;p->right->left=s;
D.s->left=p;s->right=p->right;p->right->left=s;p->right=s;
答:
D
25.在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q和p之间插入s结点,则执行______。
A.s->next=p->next;p->next=s;B.p->next=s->next;s->next=p;
C.q->next=s;s->next=p;D.p->next=s;s->next=q;
答:
C
26.从一个具有n个结点的单链表中查找其值等于x结点时,在查找成功的情况下,需平均比较_____个结点。
(参见网上讲义:
1.4.2例1_5)
A.n;B.n/2;
C.(n-1)/2;D.(n+1)/2;
答:
D
27.给定有n个结点的向量,建立一个有序单链表的时间复杂度_______。
A.O
(1);B.O(n);
C.O(n
);D.O(nlog
n);
答:
C
三、填空题
28.在一个长度为n的向量中的第i个元素(1≤i≤n)之前插入一个元素时,需向后移动_____个元素。
答:
n-i+1
29.在一个长度为n的向量中删除第i个元素(1≤i≤n)时,需向前移动_____个元素。
答:
n-i
30.在一个单链表中p所指结点之前插入一个由指针s所指结点,可执行以下操作:
s->next=__p->next_____;
p->next=s;
t=p->data;
p->data=___s->data________;
s->data=___t________;
四、算法设计题:
31.有一个单链表(不同结点的数据域值可能相同),其头指针为head,编写一个函数计算数据域为x的结点个数。
解:
本题是遍历通过该链表的每个结点,每遇到一个结点,结点个数加1,结点个数存储在变量n中。
实现本题功能的函数如下:
intcount(head,x)
node*head;
ElemTypex;
{node*p;
intn=0;
p=head;
while(p!
=NULL)
{
if(p->data==x)n++;
p=p->next;
}
return(n);
}
32.有一个有序单链表(从小到大排序),表头指针为head,编写一个函数向该单链表中插入一个元素为x的结点,使插入后该链表仍然有序。
解:
本题算法的思想是先建立一个待插入的结点,然后依次与链表中的各结点的数据域比较大小,找出该结点的位置,最后插入该结点。
实现本题功能的函数如下:
node*insertorder(head,x)
node*head;
ElemTypex;
{node*s,*p,*q;
s=(node*)malloc(sizeof(node));
s->data=x;
s->next=NULL;
if(head==NULL‖xdata)
{s->next=head;
head=s;
}
else
{
q=head;
p=q->next;
while(p!
=NULL&&x>p->data)
if(x>p->data)
{
q=p;
p=p->next;
}
s->next=p;
q->next=s;
}
return(head);
}
33.编写一个函数将一个头指针为a的单链表A分解成两个单链表A和B,其头指针分别为a和b,使得A链表中含有原链表A中序号为奇数的元素,而B链表中含有原链表A中序号为偶数的元素,且保持原来的相对顺序。
解:
其函数是将单链表A中的所有偶数序号的结点删除,并在删除时把这些结点链接起来构成单链表B。
实现本题功能的函数如下:
voiddisa(a,b)
node*a,*b;
{node*r,*p,*q;
p=a;
b=a->next;
r=b;
while(p!
=NULL&&p->next!
=NULL)
{
q=p->next;
p->next=q->next;
r->next=q;
r=q
p=p->next;
}
r->next=NULL;
}
34.假设有两个已排序的单链表A和B,编写一个函数将它们合并成一个链表C而不改变其排序性。
解:
这里采用链表合并的方法,设原两链表的头指针分别为p和q,每次比较p->data和q->data的值,把值较小的结点作为新链表的结点,这一过程直到一个链表为空为止。
当一个链表为空而另一个链表不为空时,只要将不空的链表指针赋给新链表中最后一个结点的指针即可。
实现本题功能的函数如下:
node*mergelink(p,q)
node*p,*q;
{node*h,*r;
h=(node*)malloc(sizeof(node));
h->next=NULL;
r=h;
while(p!
=NULL&&q!
=NULL)
if(p->data<=q->data)
{
r->next=p;
r=p;
p=p->next;
}
else
{
r->next=q;
r=q;
q=q->next;
}
if(p==NULL)
r->next=q;
if(q==NULL)
r->next=p;
/*下面三句要去掉链表C的头结点,如果不想去掉,则不要这三句*/
p=h->next;
h=h->next;
free(p);
returnh;
}
35.设A=(a
…,a
)和B=(b
…,bn)均为顺序表,A’和B’分别为A和B中除去最大共同前缀后的子表(例如,A=(x,y,y,z,x,z),B=(x,y,y,z,y,x,x,z),则两者中最大的共同前缀为(x,y,y,z),在A’=B’=空表,则A=B;若A’=空表,而B’<>空表,或者两者均不为空表,且A’的首元小于B’的首元,则AB。
(词典次序)试写一个比较A,B大小的算法(在算法中,不要破坏原表A和B,并且不一定先求得A’和B’才进行比较)。
36.设有一个用向量表示的线性表L,要求写出一个将该表逆置的过程,并允许在原表的存储空间外再增加一个附加的工作单元。
(朱儒荣,C语言版数据结构考研例题)
解:
用数据类型描述Seqlist顺序存储结构:
voldconverts(seqlistL)
{k=L.length;
m=k/2;
for(i=0;ix=L.element[i];
L.element[i]=L.element[k-i-1];
L.element[k-i-1]=x;
}
}//converts
讨论:
这个算法过程只须进行数据元素的交换操作,其主要时间花费在for循环上,整个算法的时间复杂度为O(k)。
37.已知两个整数集合A和B,它们的元素分别依元素值递增有序存放在两个单链表HA和HB中,编写一个函数求出这两个集合的并集C,并要求集合C的链表的结点仍依元素值递增有序存放。
(提示:
求并集不是归并!
)
38.已知两个顺序表A和B分别表示两个集合,其元素递增排列,编写一个函数求出A和B的交集C,要求C同样以元素递增的顺序表形式存储。
voidSqList_Intersect(SqListA,SqListB,SqList&C)//求元素递增排列的线性表A和B的元素的交集并存入C中
{i=0;j=0;k=0;
while(A.elem[i]&&B.elem[j])
{if(A.elem[i]i++;
if(A.elem[i]>B.elem[j])j++;
if(A.elem[i]==B.elem[j]){C.elem[k++]=A.elem[i];//当发现了一个在A,B中都存在的元素,i++;j++;//就添加到C中
}}//while}//SqList_Intersect
栈和队列
判断题
1.栈和队列都是限制存取点的线性结构(TRUE)
2.栈和队列是两种重要的线性结构。
(TRUE)
3.带头结点的单链表形式的队列,头指针F指向队列的头结点,尾指针R指向队列的最后一个结点(TRUE)
4.在对不带头结点的链队列作出队操作时,不会改变头指针的值。
(FALSE)
单项选择题:
5.若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,pn,若p1=n,则pi为(C)。
A.iB.n=iC.n-i+1D.不确定
6.栈和队列的共同点是(C)。
A.都是先进后出B.都是先进先出
C.只允许在端点处插入和删除元素D.没有共同点
7.若依次输入数据元素序列{a,b,c,d,e,f,g}进栈,出栈操作可以和入栈操作间隔进行,则下列哪个元素序列可以由出栈序列得到?
(A)
A.{d,e,c,f,b,g,a}B.{f,e,g,d,a,c,b}
C.{e,f,d,g,b,c,a}D.{c,d,b,e,g,a,f}
8.一个栈的入栈序列是1,2,3,4,5,则下列序列中不可能的出栈序列是(B)
A.2,3,4,1,5B.5,4,1,3,2
C.2,3,1,4,5D.1,5,4,3,2
9.队列操作的原则是(A)
A.先进先出B.后进先出C.只能进行插入D.只能进行删除
10.栈的插入与删除是在(A)进行。
A.栈顶B.栈底C.任意位置D.指定位置
11.假设顺序栈的定义为:
typedefstruct{
selemtype*base;/*栈底指针*/
selemtype*top;/*栈顶指针*/
intstacksize;/*当前已分配的存储空间,以元素为单位*/
}sqstack;
变量st为sqstack型,则栈st为空的判断条件为(D)。
A.st.base==NULLB.st.top==st.stacksize
C.st.top-st.base>=st.stacksizeD.st.top==st.base
12.假设顺序栈的定义同上题,变量st为sqstack型,则栈st为满的判断条件为(C)。
A.st.base==NULLB.st.top==st.stacksize
C.st.top-st.base>=st.stacksizeD.st.top==st.base
13.判断一个循环队列QU(m0为最大队列长度(以元素为单位),front和rear分别为队列的队头指针和队尾指针)为空队列的条件是(A)。
A.QU->front==QU->rearB.QU->front!
=QU->rear
C.QU->front==(QU->rear+1)%m0D.QU->front!
=(QU->rear+1)%m0
填空题:
17.线性表、栈、队列都是线性结构,可以在线性表的_________位置插入和删除元素,对于栈只能在_________位置插入和删除元素,对于队只能在________位置插入和只能在_________位置删除元素。
答:
任何、栈顶、队尾、队头
18.用S表示入栈操作,X表示出栈操作,若元素入栈顺序为1,2,3,4,为了得到1,3,4,2出栈顺序相应的S和X操作串为_____SXSSXSXX______。
19.用下标0开始的N元数组实现循环队列时,为实现下标变量m加1后在数组有效下标范围内循环,可采用的表达式是:
m=__(m+1)%N____。
20.在一个链栈中,若栈顶指针等于NULL则为_______________,在一个链队中,若队首指针与队尾指针的值相同,则表示该队列为____________或该队列______________。
答:
栈空、空队、只有一个元素
21.向一个栈顶指针为HS的链栈中插入一个新结点*P,应执行和
操作。
答:
P->next=HS、HS=P
22.从一个栈顶指针为HS的非空链栈中删除结点并不需要返回栈顶结点的值和回收结点时,应执行操作。
答:
HS=HS->next
23.设栈S和队列Q的初始状态皆为空,元素a1,a2,a3,a4,a5和a6依次通过一个栈,一个元素出栈后即进入队列Q,若6个元素出队列的顺序是a3,a5,a4,a6,a2,a1则栈S至少应该容纳个元素。
答:
4个
24.栈的顺序存储结构即顺序栈,是利用来依次存放自栈底至栈顶的数据元素;当栈为非空时,栈顶指针top始终指向。
答:
一组地址连续的存储单元栈顶元素的下一位置
25.带有头结点的链队列,当其为空的链队列的判断条件为。
答:
头指针和尾指针均指向头结点
26.从数据结构的角度看,栈和队列是两类线性表,但从数据类型角度看,它们是两类重要的抽象数据类型。
答:
受限制的与线性表大不相同的
算法设计题:
27.假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意不设头指针),试编写相应的队列初始化、入队列和出队列的算法。
解:
voidInitCiQueue(CiQueue&Q)//初始化循环链表表示的队列Q
{
Q=(CiLNode*)malloc(sizeof(CiLNode));
Q->next=Q;
}//InitCiQueue
voidEnCiQueue(CiQueue&Q,intx)//把元素x插入循环链表表示的队列Q,Q指向队尾元素,Q->next指向头结点,Q->next->next指向队头元素
{
p=(CiLNode*)malloc(sizeof(CiLNode));
p->data=x;
p->next=Q->next;//直接把p加在Q的后面
Q->next=p;
Q=p;//修改尾指针
}
StatusDeCiQueue(CiQueue&Q,intx)//从循环链表表示的队列Q头部删除元素x
{
if(Q==Q->next)returnINFEASIBLE;//队列已空
p=Q->next->next;
x=p->data;
Q->next->next=p->next;
free(p);
returnOK;
}//DeCiQueue
28.利用两个栈s1,s2模拟一个队列时,如何用栈的运算来实现该队列的运算:
enqueue:
插入一个元素;
dequeue:
删除一个元素;
queue_empty:
判定队列为空。
解:
由于栈的特点是先进后出,为了模拟先进先出的队列,必须用两个栈,一个栈s1用于插入