山东师范大学数据结构考研真题.docx
《山东师范大学数据结构考研真题.docx》由会员分享,可在线阅读,更多相关《山东师范大学数据结构考研真题.docx(39页珍藏版)》请在冰豆网上搜索。
![山东师范大学数据结构考研真题.docx](https://file1.bdocx.com/fileroot1/2023-1/8/72f18c44-03e3-4db4-a193-9594f32d6aa5/72f18c44-03e3-4db4-a193-9594f32d6aa51.gif)
山东师范大学数据结构考研真题
第1章绪论
一、选择题
1.算法的时间复杂度取决于(C)
A.问题的规模B.待处理数据的初态C.A和B
2.计算机算法指的是(C),它必须具备(B)这三个特性。
(1)A.计算方法B.排序方法C.解决问题的步骤序列D.调度方法
(2)A.可执行性、可移植性、可扩充性B.可执行性、确定性、有穷性
C.确定性、有穷性、稳定性D.易读性、稳定性、安全性
3.从逻辑上可以把数据结构分为(C)两大类。
A.动态结构、静态结构B.顺序结构、链式结构
C.线性结构、非线性结构D.初等结构、构造型结构
4.以下与数据的存储结构无关的术语是(D)。
A.循环队列B.链表C.哈希表D.栈
5.在下面的程序段中,对x的赋值语句的频度为(C)
FORi:
=1TOnDO
FORj:
=1TOnDO
x:
=x+1;
A.O(2n)B.O(n)C.O(n2)D.O(log2n)
6.连续存储设计时,存储单元的地址(A)。
A.一定连续B.一定不连续C.不一定连续D.部分连续,部分不连续
二、判断题
1.数据元素是数据的最小单位。
(F)【山东师范大学2001一、1(2分)】
2.记录是数据处理的最小单位。
(F)
3.数据的物理结构是指数据在计算机内的实际存储形式。
(T)【山东师范大学2001一、2(2分)】
4.在顺序存储结构中,有时也存储数据结构中元素之间的关系。
(F)
5.顺序存储方式的优点是存储密度大,且插入、删除运算效率高。
(F)
三、填空
1.数据的物理结构包括的表示和的表示。
2.对于给定的n个元素,可以构造出的逻辑结构有
(1),
(2),(3),_(4)四种。
3.数据的逻辑结构是指。
4.一个数据结构在计算机中称为存储结构。
5.数据结构中评价算法的两个重要指标是
6.已知如下程序段
FORi:
=nDOWNTO1DO{语句1}
BEGIN
x:
=x+1;{语句2}
FORj:
=nDOWNTOiDO{语句3}
y:
=y+1;{语句4}
END;
语句1执行的频度为
(1);语句2执行的频度为
(2);语句3执行的频度为(3);语句4执行的频度为(4)。
答案:
1.数据元素数据元素间关系2.集合线性结构树形结构图状结构或网状结构。
3.数据的组织形式,即数据元素之间逻辑关系的总体。
而逻辑关系是指数据元素之间的关联方式或称“邻接关系”。
4.表示(映像)。
5.时间复杂度和空间复杂度。
6.
(1)n+1
(2)n(3)n(n+3)/2(4)n(n+1)/2。
四、应用题
1.数据元素之间的关系在计算机中有几种表示方法?
各有什么特点?
四种表示方法
(1)顺序存储方式。
数据元素顺序存放,每个存储结点只含一个元素。
存储位置反映数据元素间的逻辑关系。
存储密度大,但有些操作(如插入、删除)效率较差。
(2)链式存储方式。
每个存储结点除包含数据元素信息外还包含一组(至少一个)指针。
指针反映数据元素间的逻辑关系。
这种方式不要求存储空间连续,便于动态操作(如插入、删除等),但存储空间开销大(用于指针),另外不能折半查找等。
(3)索引存储方式。
除数据元素存储在一地址连续的内存空间外,尚需建立一个索引表,索引表中索引指示存储结点的存储位置,兼有静态和动态特性。
(4)散列存储方式。
通过散列函数和解决冲突的方法,将关键字散列在连续的有限的地址空间内,并将散列函数的值解释成关键字所在元素的存储地址,这种存储方式称为散列存储。
其特点是存取速度快,只能按关键字随机存取,不能顺序存取,也不能折半存取。
2.若有100个学生,每个学生有学号,姓名,平均成绩,采用什么样的数据结构最方便,写出这些结构?
【山东师范大学1996二、2】
将学号、姓名、平均成绩看成一个记录(元素,含三个数据项),将100个这样的记录存于数组中。
因一般无增删操作,故宜采用顺序存储。
typedefstruct
{intnum;//学号
charname[8];//姓名
floatscore;/平均成绩
}node;
nodestudent[100];
第2章线性表
一选择题
1.线性表是具有n个(数据元素)的有限序列(n>0)。
2.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用(顺序表)存储方式最节省时间。
3.某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用(仅有尾指针的单循环链表)存储方式最节省运算时间。
4.设一个链表最常用的操作是在末尾插入结点和删除尾结点,则选用(D)最节省时间。
A.单链表B.单循环链表C.带尾指针的单循环链表D.带头结点的双循环链表
5.若某表最常用的操作是在最后一个结点之后插入一个结点或删除最后一个结点。
则采用(D)存储方式最节省运算时间。
A.单链表B.双链表C.单循环链表D.带头结点的双循环链表
6.链表不具有的特点是(B)
A.插入、删除不需要移动元素B.可随机访问任一元素
C.不必事先估计存储空间D.所需空间与线性长度成正比
7.下面的叙述不正确的是(BC)
A.线性表在链式存储时,查找第i个元素的时间同i的值成正比
B.线性表在链式存储时,查找第i个元素的时间同i的值无关
C.线性表在顺序存储时,查找第i个元素的时间同i的值成正比
D.线性表在顺序存储时,查找第i个元素的时间同i的值无关
8.若长度为n的线性表采用顺序存储结构,在其第i个位置插入一个新元素的算法的时间复杂度为(C)(1<=i<=n+1)。
A.O(0)B.O
(1)C.O(n)D.O(n2)
9.对于顺序存储的线性表,访问结点和增加、删除结点的时间复杂度为(C)。
A.O(n)O(n)B.O(n)O
(1)C.O
(1)O(n)D.O
(1)O
(1)
10.线性表(a1,a2,…,an)以链接方式存储时,访问第i位置元素的时间复杂性为(C)
A.O(i)B.O
(1)C.O(n)D.O(i-1)
11.非空的循环单链表head的尾结点p↑满足(A)。
A.p↑.link=headB.p↑.link=NILC.p=NILD.p=head
12.完成在双循环链表结点p之后插入s的操作是(D);
A.p^.next:
=s;s^.priou:
=p;p^.next^.priou:
=s;s^.next:
=p^.next;
B.p^.next^.priou:
=s;p^.next:
=s;s^.priou:
=p;s^.next:
=p^.next;
C.s^.priou:
=p;s^.next:
=p^.next;p^.next:
=s;p^.next^.priou:
=s;
D.s^.priou:
=p;s^.next:
=p^.next;p^.next^.priou:
=s;p^.next:
=s;
13.在单链表指针为p的结点之后插入指针为s的结点,正确的操作是:
()。
14.对于一个头指针为head的带头结点的单链表,判定该表为空表的条件是()
A.head==NULLB.head→next==NULLC.head→next==headD.head!
=NULL
15.在双向链表存储结构中,删除p所指的结点时须修改指针()。
16.双向链表中有两个指针域,llink和rlink分别指向前趋及后继,设p指向链表中的一个结点,现要求删去p所指结点,正确的步骤是()链中结点数大于2,p不是第一个结点)。
二、判断
2.顺序存储结构的主要缺点是不利于插入或删除操作。
(T)
3.线性表采用链表存储时,结点和结点内部的存储空间可以是不连续的。
(T)
4.顺序存储方式插入和删除时效率太低,因此它不如链式存储方式好。
(F)
5.对任何数据结构链式存储结构一定优于顺序存储结构。
(F)
6.顺序存储方式只能用于存储线性结构。
(F)
7.集合与线性表的区别在于是否按关键字排序。
(F)
9.线性表的特点是每个元素都有一个前驱和一个后继。
(F)
10.取线性表的第i个元素的时间同i的大小有关.(F)
11.循环链表不是线性表.(F)
12.线性表只能用顺序存储结构实现。
(F)
13.线性表就是顺序存储的表。
(F)
14.为了很方便的插入和删除数据,可以使用双向链表存放数据。
(T)
三、填空
1.线性表L=(a1,a2,…,an)用数组表示,假定删除表中任一元素的概率相同,则删除一个元素平均需要移动元素的个数是((n-1)/2)。
2.设单链表的结点结构为(data,next),next为指针域,已知指针px指向单链表中data为x的结点,指针py指向data为y的新结点,若将结点y插入结点x之后,则需要执行以下语句:
(py->next=px->next;px->next=py);
3.在单链表中设置头结点的作用是(主要是使插入和删除等操作统一,在第一个元素之前插入元素和删除第一个结点不必另作判断)。
4.顺序存储结构是通过(物理上相邻)表示元素之间的关系的;链式存储结构是通过(指针)表示元素之间的关系的。
5.带头结点的双循环链表L中只有一个元素结点的条件是:
(L->next->next==L)
6.在单链表L中,指针p所指结点有后继结点的条件是:
(p->next!
=null)
7.带头结点的双循环链表L为空表的条件是:
(L->next==L&&L->prior==L)。
四应用题
1.链式存储结构一般说克服了顺序存储结构的三个弱点。
首先,插入、删除不需移动元素,只修改指针,时间复杂度为O
(1);其次,不需要预先分配空间,可根据需要动态申请空间;其三,表容量只受可用内存空间的限制。
其缺点是因为指针增加了空间开销,当空间不允许时,就不能克服顺序存储的缺点。
2.线性表的链式存储结构中,头指针与头结点之间的根本区别;头结点与首元结点的关系。
在线性表的链式存储结构中,头指针指链表的指针,若链表有头结点则是链表的头结点的指针,头指针具有标识作用,故常用头指针冠以链表的名字。
头结点是为了操作的统一、方便而设立的,放在第一元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等),有头结点后,对在第一元素结点前插入结点和删除第一结点,其操作与对其它结点的操作统一了。
而且无论链表是否为空,头指针均不为空。
首元结点也就是第一元素结点,它是头结点后边的第一个结点。
3.设单链表中某指针p所指结点(即p结点)的数据域为data,链指针域为next,请写出在p结点之前插入s结点的操作。
(若头节点未知,则后插交换)
设单链表的头结点的头指针为head,且pre=head;
while(pre->next!
=p)pre=pre->next;
s->next=p;pre->next=s;
4.设双向循环链表中结点的数据域、前驱和后继指针域分别为data,pre和next,试写出在指针p所指结点之前插入一s结点的算法。
五、算法设计题
1.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。
请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。
LinkedListUnion(LinkedListla,lb)
∥la,lb分别是带头结点的两个单链表的头指针,链表中的元素值按递增序排列,本算法将两链表合并成一个按元素值递减次序排列的单链表。
{pa=la->next;pb=lb->next;∥pa,pb分别是链表la和lb的工作指针
la->next=null;∥la作结果链表的头指针,先将结果链表初始化为空。
while(pa!
=null&&pb!
=null)∥当两链表均不为空时作
if(pa->data<=pb->data)
{r=pa->next;∥将pa的后继结点暂存于r。
pa->next=la->next;∥将pa结点链于结果表中,同时逆置。
la->next=pa;
pa=r;}∥恢复pa为当前待比较结点。
else
{r=pb->next;∥将pb的后继结点暂存于r。
pb->next=la->next;∥将pb结点链于结果表中,同时逆置。
la->next=pb;
pb=r;}∥恢复pb为当前待比较结点。
while(pa!
=null)∥将la表的剩余部分链入结果表,并逆置。
{r=pa->next;pa->next=la->next;la->next=pa;pa=r;}
while(pb!
=null)
{r=pb->next;pb->next=la->next;la->next=pb;pb=r;}
}∥算法Union结束。
[算法讨论]上面两链表均不为空的表达式也可简写为while(pa&&pb),两递增有序表合并成递减有序表时,上述算法是边合并边逆置。
也可先合并完,再作链表逆置。
后者不如前者优化。
算法中最后两个while语句,不可能执行两个,只能二者取一,即哪个表尚未到尾,就将其逆置到结果表中,即将剩余结点依次前插入到结果表的头结点后面。
2.已知头指针分别为la和lb的带头结点的单链表中,结点按元素值非递减有序排列。
写出将la和lb两链表归并成一个结点按元素值非递减有序排列的单链表(其头指针为lc),并计算算法的时间复杂度。
(课本31页)
本题与上题类似,要求结果指针为lc,其核心语句段如下:
pa=la->next;pb=hb->next;
lc=(LinkedList)malloc(sizeof(LNode));
pc=lc;∥pc是结果链表中当前结点的前驱
while(pa&&pb)
if(pa->datadata)
{pc->next=pa;pc=pa;pa=pa->next;}
else{pc->next=pb;pc=pb;pb=pb->next;}
if(pa)pc->next=pa;elsepc->next=pb;
free(la);free(lb);∥释放原来两链表的头结点。
算法时间复杂度为O(m+n),其中m和n分别为链表la和lb的长度。
3.已知递增有序的两个单链表A,B分别存储了一个集合。
设计算法实现求两个集合的交集的运算A:
=A∩B
本题是求交集,即只有同时出现在两集合中的元素才出现在结果表中。
核心语句段如下:
pa=la->next;pb=lb->next;∥设工作指针pa和pb;
pc=la;∥结果表中当前合并结点的前驱的指针。
while(pa&&pb)
if(pa->data==pb->data)∥交集并入结果表中。
{pc->next=pa;pc=pa;pa=pa->next;
u=pb;pb=pb->next;free(u);}
elseif(pa->datadata){u=pa;pa=pa->next;free(u);}
else{u=pb;pb=pb->next;free(u);}
while(pa){u=pa;pa=pa->next;free(u);}∥释放结点空间
while(pb){u=pb;pb=pb->next;free(u);}∥释放结点空间
pc->next=null;∥置链表尾标记。
4.已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为0(n)、空间复杂度为0
(1)的算法,该算法删除线性表中所有值为item的数据元素。
[题目分析]在顺序存储的线性表上删除元素,要涉及到一系列元素的移动(删第i个元素,第i+1至第n个元素要依次前移)。
本题要求删除线性表中所有值为item的数据元素,并未要求元素间的相对位置不变。
因此可以考虑设头尾两个指针(i=1,j=n),从两端向中间移动,凡遇到值item的数据元素时,直接将右端元素左移至值为item的数据元素位置。
voidDelete(ElemTypeA[],intn)
∥A是有n个元素的一维数组,本算法删除A中所有值为item的元素。
{i=1;j=n;∥设置数组低、高端指针(下标)。
while(i{while(i=item)i++;∥若值不为item,左移指针。
if(iif(i}
[算法讨论]因元素只扫描一趟,算法时间复杂度为O(n)。
5.在一个递增有序的线性表中,有数值相同的元素存在。
若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素。
题目分析]在递增有序的线性表中,删除数值相同的元素,要知道被删除元素结点的前驱结点。
LinkedListDelSame(LinkedListla)
∥la是递增有序的单链表,本算法去掉数值相同的元素,使表中不再有重复的元素。
{pre=la->next;∥pre是p所指向的前驱结点的指针。
p=pre->next;∥p是工作指针。
设链表中至少有一个结点。
while(p!
=null)
if(p->data==pre->data)∥处理相同元素值的结点
{u=p;p=p->next;free(u);}∥释放相同元素值的结点
else{pre->next=p;pre=p;p=p->next;}∥处理前驱,后继元素值不同
pre->next=p;∥置链表尾。
}∥DelSame
6.假设一个单循环链表,其结点含有三个域pre、data、link。
其中data为数据域;pre为指针域,它的值为空指针(NIL);link为指针域,它指向后继结点。
请设计算法,将此表改成双向循环链表。
[题目分析]将具有两个链域的单循环链表,改造成双向循环链表,关键是控制给每个结点均置上指向前驱的指针,而且每个结点的前驱指针置且仅置一次。
voidStoDouble(LinkedListla)
∥la是结点含有pre,data,link三个域的单循环链表。
其中data为数据域,pre为空指针域,link是指向后继的指针域。
本算法将其改造成双向循环链表。
{while(la->link->pre==null)
{la->link->pre=la;∥将结点la后继的pre指针指向la。
la=la->link;∥la指针后移。
}}∥算法结束。
[算法讨论]算法中没有设置变量记住单循环链表的起始结点,至少省去了一个指针变量。
当算法结束时,la恢复到指向刚开始操作的结点,这是本算法的优点所在。
第3章栈和队列
一填空题
1.输入序列为ABC,可以变为CBA时,经过的栈操作为(push,push,push,pop,pop,pop)
2.若栈采用顺序存储方式存储,现两栈共享空间V[1..m],top[i]代表第i个栈(i=1,2)栈顶,栈1的底在v[1],栈2的底在V[m],则栈满的条件是(top[1]+1=top[2])。
3.表达式a*(b+c)-d的后缀表达式是(abc+*d-)。
4.栈的特点是(后进先出),队列的特点是(先进先出),栈和队列都是(限制存取点的线性结构)。
若进栈序列为1,2,3,4则(4,2,3,1)不可能是一个出栈序列(不一定全部进栈后再出栈);若进队列的序列为1,2,3,4则(1,2,3,4)是一个出队列序列。
5.当两个栈共享一存储区时,栈利用一维数组stack(1,n)表示,两栈顶指针为top[1]与top[2],则当栈1空时,top[1]为__0__,栈2空时,top[2]为__n+1__,栈满时为__top[1]+1=top[2]_。
6.已知链队列的头尾指针分别是f和r,则将值x入队的操作序列是(s->data=x;s->next=r->next;r->next=s;r=s;)。
7.设循环队列存放在向量sq.data[0:
M]中,则队头指针sq.front在循环意义下的出队操作可表示为(sq.front=(sq.front+1)%(M+1);return(sq.data(sq.front)),若用牺牲一个单元的办法来区分队满和队空(设队尾指针sq.rear),则队满的条件为(sq.rear+1)%(M+1)==sq.front。
二判断题
1.消除递归不一定需要使用栈(T)。
2.两个栈共享一片连续内存空间时,为提高内存利用率,减少溢出机会,应把两个栈的栈底分别设在这片内存空间的两端。
(T)
3.即使对不含相同元素的同一输入序列进行两组不同的合法的入栈和出栈组合操作,所得的输出序列也一定相同。
(F)
4.栈与队列是一种特殊操作的线性表。
(T)
5.若输入序列为1,2,3,4,5,6,则通过一个栈可以输出序列3,2,5,6,4,1.(T)
6.任何一个递归过程都可以转换成非递归过程。
( T )
7.队列和栈都是运算受限的线性表,只允许在表的两端进行运算。
(F)
8.栈和队列的存储方式,既可以是顺序方式,又可以是链式方式。
(T)
三算法设计题
1.设输入序列为2,3,4,5,6,利用一个栈能得到序列2,5,3,4,6吗?
栈可以用单链表实现吗?
【山东师范大学1996五、4(2分)】
不能得到序列2,5,3,4,6。
栈可以用单链表实现,这就是链栈。
由于栈只在栈顶操作,所以链栈通常不设头结点。
2.从键盘上输入一个逆波兰表达式,用伪码写出其求值程序。
规定:
逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。
例如:
23434+2*$【山东师范大学1999七(10分)】
floatexpr()
//从键盘输入逆波兰表达式,以‘$’表示输入结束,本算法求逆波兰式表达式的值。
{floatOPND[30];//OPND是操作数栈。
init(OPND);//两栈初始化。
floatnum=0.0;//数字初始化。
scanf(“%c”,&x);//x是字符型变量。
while(x!
=’$’)
{switch
{case‘0’<=x<=’9’:
while((x>=’0’&&x<=’9’)||x==’.’)//拼数
if(x!
=’.’)//处理整数
{num=num*10+(ord(x)-ord(‘0’));scanf(“%c”,&x);}
else//处理小数部分。
{scale=10.0;scanf(“%c”,&x);
while(x>=’0’&&x<=’9’)
{num=num+(ord(x)-ord(‘0’)/scale;
scale=scale*10;scanf(“%c”,&x);}
}//else
push(OPND,num);num