数据结构复习题
第一章 绪论
一、填空题
1、数据结构被形式地定义为(D, R),其中D是 数据的 有限集合,R是 关系的 有限集合。
2、数据结构包括数据的 逻辑结构 、数据的 物理结构 和数据的 运算 这个方面的内容。
3、数据结构按逻辑结构可分为两大类,它们分别是 线性的 和 非线性的 。
4、线性结构中元素之间存在 一对一 关系,树形结构中元素之间存在 一对多 的关系。
5、数据的存储结构可用四种基本的存储方法表示,它们分别是 顺序存储、 链式存储、索引存储、 散列存储 。
6、数据的运算常用的有5种,它们分别是 插入、删除、查找、排序、修改 。
7、一个算法的效率可分为 时间 效率和 空间 效率
二、单项选择题
1. 非线性结构是数据元素之间存在一种: B
A、一对多关系 B、多对多关系 C、多对一关系 D、一对一关系
2. 数据结构中,与所使用的计算机无关的是数据的什么结构; C
A、存储 B、 物理 C、 逻辑 D、 物理和存储
3. 算法分析的目的是: C
A、找出数据结构的合理性 B、研究算法中的输入和输出的关系
C、 分析算法的效率以求改进 D、分析算法的易懂性和文档性
4. 算法分析的两个主要方面是: A
A、 空间复杂性和时间复杂性 B、正确性和简明性
C、 可读性和文档性 D、数据复杂性和程序复杂性
5. 计算机算法指的是: C
A、计算方法 B、排序方法 C、解决问题的有限运算序列 D、调度方法
1. for (i=0; i<n; i++) for (j=0; j<m; j++) A[i][j]=0; |
三、分析下面各程序段的时间复杂度
两个for循环嵌套,第一个规模是n,内循环规模是m,所以整个程序的时间复杂度为O(m*n)
2. s=0; for (i=0; i<n; i++) for(j=0; j<n; j++) s+=B[i][j]; sum=s; |
两个for循环嵌套,第一个规模是n,内循环规模是分别是1,2,3,…,故整个程序的时间效率为:1+2+3+…+n=n(n+1)/2=O(n*n)
3. x=0; for(i=1; i<n; i++) for (j=1; j<=n-i; j++) x++;
|
4. i=1; while(i<=n) i=i*3;
|
与上一条类似,内循环相反,故整个程序的时间效率为: n+n-1+…+3+2+1=n(n+1)/2=O(n*n)
假设整个循环次数为fn,则有3f(n)≤n
,故,该程序的时间效率为O(log3n
)
四、应用题:
- 简述将一个现实问题转化为可用计算机解决的过程
答:第一步,分析:对现实问题进行分析,找出已知条件和要求解的结果;
第二步,建模:依据第一步分析结果,采用相关知识构建求解模型,这一步的关键是相关知识对具体问题的吻合度;
第三步,实现:利用开发工具,在计算机上编写应用程序,开发求解软件。
- 简述构建或使用函数应关注那些属性
答:函数名、函数的参数、函数的返回值、函数体。
其中,函数名需要有一定的意义,以便于他人的调用,函数的参数个数、类型、可否缺省等是正确调用一个函数的关键,函数的返回值类型是函数是否被正确调用的又一关键,函数体的编写体现了函数开发者的水平。
- 设有数据逻辑结构S=(D,R),试按各小题所给条件画出这些逻辑结构的图示,并确定相对应关系R,哪些结点是开始结点,哪些结点是终端结点(也叫度为0的点)?
1、D={d1,d2,d3,d4}
R={(d1,d2),(d2,d3),(d3,d4) }
d1->d2->d3->d4 线性 开始节点d1 终端结点d4
2、D={d1,d2,…,d9}
d6 |
d1 |
d2 |
d3 |
d4 |
d55 |
d7 |
d8 |
d9 |
非线性(树) 开始结点d1 终端结点d2 d5 d7 d9 |
R={(d1,d2),(d1,d3),(d3,d4),(d3,d6),(d6,d8),(d4,d5), (d6,d7),(d8,d9) }
3、D={d1,d2,…,d9}
d6 |
d1 |
d2 |
d3 |
d4 |
d55 |
d7 |
d8 |
d9 |
非线性 开始结点d1 d2 终端结点d6 d7 |
R={(d1,d3),(d1,d8),(d2,d3),(d2,d4),(d2,d5),(d3,d9),(d5,d6),(d8,d9),(d9,d7), (d4,d7), (d4,d6)}
4、田径赛的时间安排问题(无向图的着色问题) :设有六个比赛项目,规定每个选手至多可参加三个项目,有五人报名参加比赛(如下表所示)设计比赛日程表,使得在尽可能短的时间内完成比赛。
姓名 |
项目1 |
项目2 |
项目3 |
王兴元 |
跳高 |
跳远 |
100米 |
张玉屏 |
标枪 |
铅球 |
|
赵刚 |
标枪 |
100米 |
200米 |
吴建宇 |
铅球 |
200米 |
跳高 |
程娟 |
跳远 |
200米 |
答:(1)设用如下六个不同的代号代表不同的项目:
- 跳远 标枪 铅球 100米 200米
- B C D E F
姓名 |
项目1 |
项目2 |
项目3 |
王兴元 |
A |
B |
E |
张玉屏 |
C |
D |
|
赵刚 |
C |
E |
F |
吴建宇 |
D |
F |
A |
程娟 |
B |
F |
2)用顶点代表比赛项目:不能同时进行比赛的项目之间连上一条边。(见图)
3)某选手比赛的项目必定有边相连(不能同时比赛)。见表:
A |
B |
C |
F |
E |
D |
由图得:
比赛时间 |
可同时进行的项目 |
1 |
A,C |
2 |
B,D |
3 |
E |
4 |
F |
第二章、线性表
一、填空题
1、在顺序表中插入或删除一个元素,需要平均移动 n/2 元素,具体移动的元素个数与 插入位置 有关。
2、在顺序表中访问任意一结点的时间复杂度均为 O(C)/ O(1) ,因此,顺序表也称为 随机访问 的数据结构。
3、顺序表中逻辑上相邻的元素的物理位置 必定 相邻,单链表中逻辑上相邻的元素的物理位置 不一定 相邻。
4、在单链表中,除了首元结点外,任一结点的存储位置由 此逻辑前驱结点的指针 指示 。
5、 在n个结点的单链表中要删除已知结点*p,需找到它的 前驱结点 ,其时间复杂度为 O(n) 。
二、判断正误
( F )1、链表的每个结点中都恰好包含一个指针。
( F )2、链表的物理存储结构具有同链表表达的逻辑结构有一样的顺序。
( F )3、线性表的每个结点只能是一个简单类型,而链表的每个结点可以是一个复杂类型。
( F )4、顺序表结构适宜于进行顺序存取,而链表适宜于进行随机存取。
( F )5、顺序存储方式的优点是存储密度大,且插入、删除运算效率高。
( F )6、线性表在物理存储空间中也一定是连续的。
( F )7、线性表在顺序存储时,逻辑上相邻的元素未必在存储的物理位置次序也相邻。
( F )8、线性表的逻辑顺序与存储顺序总是一致的。
( F )9、线性表的顺序存储结构比链式存储结构更好。
( F )10、 在有序的顺序表和有序的链表上,均可以使用折半查找法来提高查找速度。
( T )11、顺序存储的线性表可以随机存取。
( T )12、线性表采用顺序存储,必须占用一片连续的存储单元。
N ( T )13、顺序存储结构属于静态存储结构,链式存储结构属于动态存储结构。
三、单项选择题
1、数据在计算机存储器内表示时,物理地址与逻辑地址相同并且是连续的,称之为:C
A、存储结构 B、逻辑结构 C、顺序存储结构 D、链式存储结构
2、一个向量第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是 B
A、110 B、108 C、100 D、120
3、在n个结点的顺序表中,算法的时间复杂度是O(1)的操作是: A
A、访问第i个结点(1≤i≤n)和求第i个结点的直接前驱(2≤i≤n)
B、在第i个结点后插入一个新结点(1≤i≤n)
C、删除第i个结点(1≤i≤n)
D、将n个结点从小到大排序
4、向一个有127个元素的顺序表中插入一个新元素并保持原来顺序不变,平均要移动多少个元素: B
A、8 B、63.5 C、63 D、7
5、链接存储的存储结构所占存储空间: A
A、分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针
B、只有一部分,存放结点值
C、只有一部分,存储表示结点间关系的指针
D、分两部分,一部分存放结点值,另一部分存放结点所占单元数
6、线性表若采用链式存储结构时,要求内存中可用存储单元的地址: D
A、必须是连续的 B、部分地址必须是连续的
C、一定是不连续的 D、连续或不连续都可以
7、线性表L在那种情况下适用于使用链式结构实现。 B
A、需经常修改L中的结点值 B、需不断对L进行删除插入
C、L中含有大量的结点 D、L中结点结构复杂
8、在非空双向循环链表(节点指针域分别为pre 和next)中q所指的结点前插入一个由p所指的链结点的过程依次为: D
A、q->pre=p; p->next=q;
B、t=q->pre; t->next=p; p->next=q;
C、t=q->pre; t->next=p; p->pre=t; p->next=q;
D、t=q->pre; t->next=p; p->next=q; q->pre=p; p->pre=t;
9、带头结点的单链表L为空的判定条件是: B
A、L==NULL B、 L->next==NULL C、 L->next==L D、 L!=NULL
10、若某表最常用的操作是在最后一个结点之后插入一个结点或删除第一个结点。则采用什么存储方式最节省运算时间:C
A、带头结点的单链表 B、不带头结点的双向链表
C、头指针指向最后一个结点的单循环链表 D、带头结点的双循环链表
四、应用题
1、试比较顺序存储结构和链式存储结构的优缺点。在什么情况下用顺序表比链表好?
顺序表需要在内存中预先开辟一个连续的、足够大的空间进行保存,
顺序表的特点是逻辑上相邻的元素在内存结点位置也要相邻,即逻辑相邻物理也相邻。存储密度高,为1,
顺序表在定位查找比较快捷,但插入删除需要移动大量元素,所以时间效率不高。
链表由于采用指针表示数据元素原先的逻辑关系,因此,链表不需要预先开辟空间,每需要一个存储单元就申请一个,
链表中元素的逻辑关系依赖指针保持,因此逻辑上相邻的元素不需要保证物理的相邻,由于有一个指针域,所以链表的存储密度小于1,
链表可以高效的插入删除,但如果要查找某一位置的值,需要从链头指针出发,依次向下查找,效率不高,为O(n)。
2、描述以下三个概念的区别:头指针、头结点、首元结点(第一个元素结点)。在单链表中设置头结点的作用是什么?
答:一个链表在内存中保存的形态是一个个链结点由指针串联而成,一般而言,访问该链表是从该链的第一个结点出发、依次向下进行,因此一个链表的第一个结点的位置非常重要,给它一个名称:头指针。可以想象,对一个单链表而言,如果丢掉了头指针,则也就丢失了该链表。
首元结点,是指一个链表中存放逻辑第一个元素所在的结点,常常的,链表的头指针就指向首元结点。
但一些链表为了编程方便或其他原因,在首元结点前又放置一个结点,该结点的数据域存放了链表的辅助信息,诸如链表的长度、数据类型等,此时,该链表的头指针指向该结点,该结点的指针域指向首元结点,称这个结点为头结点。
五、算法分析题(给出算法思想,可以选择一两条用C构建实现函数)
1、顺序表按序号查找
return array[target];
2、顺序表按值查找
for(i=0; i<length; ++i)
if(array[i] == target)
break;
3、顺序表逆置
for(i=0; i<length; ++i)
new_array[length-i-1] = array[i];
4、有序顺序表插入
for(i=length; target<array[i-1]; --i)
array[i] = array[i-1];
array[i] = target;
5、求单链表长度
while(p){
++i;
p=p->next;
}
6、单链表建立
while(a!='$'){ //预设 $ 为结束信号
s=malloc(sizeof(linklist));
s->data=a;
p->next=s;
p=s;
scanf("%c",&a);
}
p->next=NULL;
7、单链表按序号查找
for(i=0;i<target;++i) p=p->next;
8、单链表按值查找
while(p){
if(p->data==target) return p;
else p=p->next;
}
9、单链表插入
p->next= malloc(sizeof(linklist));
10、单链表逆置
提示:需要三个额外指针
r = head;
s = r->next;
t = s->next;
r->next=NULL;
while (t != NULL) {
s->next = r;
r = s;
s = t;
t = s->next;
}
s->next = r;
head = s;
第三章:栈和队列
一、填空题
1、 线性表、栈和队列都是 线性 结构,可以在线性表的 任意 位置插入和删除元素;对于栈只能在 栈顶 插入和删除元素;对于队列只能在 队尾 插入和 队头 删除元素。
2、 栈是一种特殊的线性表,允许插入和删除运算的一端称为 栈顶 。不允许插入和删除运算的一端称为 栈底 。
3、 队列 是被限定为只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表。
4、在一个循环队列中,队首指针指向队首元素的 前一个 位置。
5、在具有n个单元的循环队列中,队满时共有 n-1 个元素。
6、 向栈中压入元素的操作是先 移动栈顶指针 后 插入元素 。
7、从循环队列中删除一个元素时,其操作是 先 判断是否队空 ,后 移动队头指针 。
8、 带表头结点的空循环双向链表的长度等于 1 。
二、判断正误
( F )1、 在表结构中最常用的是线性表,栈和队列不太常用。
( T )2、 对于不同的使用者,一个表结构既可以是栈,也可以是队列,也可以是线性表。
( F )3、 栈和链表是两种不同的数据结构。
( F )4、 栈和队列是一种非线性数据结构。
( T )5、 栈和队列的存储方式既可是顺序方式,也可是链接方式。
( T )6、 两个栈共享一片连续内存空间时,为提高内存利用率,减少溢出机会,应把两个栈的栈底分别设在这片内存空间的两端。
( F )7、 队列是一种插入与删除操作分别在表的两端进行的线性表,是一种先进后出型结构。
( F )8、 一个栈的输入序列是12345,则栈的输出序列不可能是12345。
三、单项选择题(每小题1分,共20分)
1、判定一个顺序栈ST(最多元素为m0)为空的条件是 A
A、ST->top<0 B、ST->top=0 C、ST->top<>m0 D、ST->top=m0
2、判定一个队列QU(最多元素为m0)为满队列的条件是 A
A、QU->rear - QU->front == m0 B、QU->rear - QU->front -1 == m0
C、QU->front == QU->rear D、QU->front == QU->rear+1
3、数组Q[n]用来表示一个循环队列,f为当前队列头元素的前一位置,r为队尾元素的位置,假定队列中元素的个数小于n,计算队列中元素的公式为 D
A、r-f; B、(n+f-r)% n; C、n+r-f; D、(n+r-f)% n
4、向一个栈顶指针为top的链栈中插入一个S所指结点时,则执行: C
A、 top->next = S; B、S->next = top->next; top->next = S;
C、 S->next = top; top = S; D、S->next = top; top = top->next;
5、若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,pn,若p1=n,则pi为: C
A、i B、n=i C、n-i+1 D、不确定
6、向一个栈顶指针为top的链栈中插入一个S所指结点时,则执行: C
A、top->next = S; B、S->next = top->next; top->next = S;
C、S->next = top; top = S; D、S->next = top; top = top->next;
7、若用一个大小为6的数组来实现循环队列,且当前rear和front的值分别为0和3,当从队列中删除一个元素,再加入两个元素后,rear和front的值分别为多少? C
A、1和 5 B、2和4 C、4和2 D、5和1
四、应用题
1、 说明线性表、栈与队的异同点。
答:线性表元素之间存在一对一的关系,除了第一个元素外,每一个元素都有一个唯一的前驱,除了最后一个元素外,每一个元素都有一个唯一的后续。线性表可以在任意位置插入和删除元素。
栈和队列是运算受到限制的线性表,具体而言,栈只能在表的一段插入、删除元素,该端称之为栈顶,对应的,插入删除称之为入栈和出栈,队列只能在表的一段删除,该端成为队头,在另一端插入元素,该端成为队尾。
2、 顺序队的“假溢出”是怎样产生的?如何知道循环队列是空还是满?
答:顺序队列中,由于不停的插入、删除元素,会导致队头指针前面依然有空的位置,但队尾指针已经指向数组的上标位置,此时已无法添加新的元素,这种情况,成为“假溢出”。,解决假溢出的方法是采用“循环队列”。
front =(rear+1)%maxsize
3、 设循环队列的容量为40(序号从0到39),现经过一系列的入队和出队运算后,有:(a)front=11,rear=19; (b)front=19,rear=11;问在这两种情况下,循环队列中各有元素多少个?
答:计算公式:(r-f+n)%n (a)8 (b)32
4、 1) 什么是递归程序?
2) 递归程序的优、缺点是什么?
3) 递归程序在执行时,应借助于什么来完成?
4) 递归程序的入口语句、出口语句一般用什么语句实现?
答:(1)函数体内直接或间接调用函数自身,称为“递归”;
(2)递归编程简洁方便,但效率不高;
(3)递归程序在执行时,一般采用栈来保存递归调用的中间结果;
(4)递归程序的入口语句和出口语句一般用条件判断语句来实现。
五、阅读理解(每小题5分,共20分)
1、写出下列程序段的输出结果(队列中的元素类型QElem Type为char)。
void main( ){
Queue Q;
InitQueue (Q);
Char x=’e’; y=’c’;
EnQueue (Q, ’h’); EnQueue (Q, ’r’); EnQueue (Q, y);
DeQueue (Q, x); EnQueue (Q, x);
DeQueue (Q, x); EnQueue (Q, ’a’);
while(!QueueEmpty(Q)){
DeQueue (Q,y);printf(y);
};
Printf(x);
}
答: char
2、简述以下算法的功能(栈和队列的元素类型均为int)。
void algo3(Queue &Q){
Stack S; int d;
InitStack(S);
while(!QueueEmpty(Q)){
DeQueue (Q,d); Push(S,d);
};
while(!StackEmpty(S)){
Pop(S,d); EnQueue (Q,d);
}
}
答:将队列中的原先数据转置一次(前后彻底颠倒)
六、算法设计(可以仅写出算法思想,也可以C语言函数实现)
1、假设一个算术表达式中包含圆括弧、方括弧和花括弧三种类型的括弧,编写一个判别表达式中括弧是否正确配对的函数correct(exp,tag);其中:exp为字符串类型的变量(可理解为每个字符占用一个数组元素),表示被判别的表达式,tag为布尔型变量。
提示:使用栈会便捷一点。比如:当识别到左括弧则压入栈,识别到右括弧则将其与栈顶的左括弧相匹配,匹配成功则弹出,继续识别。匹配失败(或栈顶无元素)则返回false。如字符串一直识别到最后且栈为空,则返回true。
return Q;
}
第四章:串和广义表
一 、串
1、 简述下列每个术语的区别:
空串和空格串; 串变量和串常量; 主串和子串; 串名和串值;
答:空串和空格串:空串是长度为0的串,它不包含任何字符,空格串是由空格字符组成的串,长度大于0。
串变量和串常量:编程中经常使用串变量和串常量,其中,串变量可以依需要进行多次数值变换,但必须是字符串型,而串常量一经赋值,即不能改变。
主串和子串:一个字符串中任意个连续的字符组成的子序列称为该串的子串。该串相应地称为主串。
串名和串值:一个串在程序中被定义成一个变量或常量的名称,称为该串的串名,串名实际保存的串值,称为串值,因为一般编程中,采用字符来表达变量或常量名称,所以,要注意不要搞混。
2、 用串的其他基本运算构造串的子串定位运算index。
int index(s,t){
l1=length(s);
l2=length(t);
for(i=1;i<=l1-l2){
x=sunstr(s,l1,l2);
if x==t return I;
}
return 0
}
3、设有A=””,B=”mule”,C=”old”,D=”my”,请计算下面运算的结果:
(1)strcat(A,B)
(2)substr(B,3,2)
(3)strlen(A)
(4)index(B,D)
(5)insert(B,1,A)
(6)replace(C,2,2,”k”)
答:(1)strcat(A,B)=”mule”
(2) substr(B,3,2)=”le”
(3) strlen(A)=0
(4) index(B,D)=0
(5) insert(B,1,A)= “mule”
(6) replace(C,2,2,”k”)=”ok”
4、 已知:S=”(xyz)”,T=”(x+z)*y”,利用联接、求子串和置换等基本运算,将S转换为T。
答:T1=sunstr(s,2,1)
T2=substr(s,3,1)
T3=substr(s,4,1)
T=strcat(“(”,t1)
T=strcat(T,”+”)
T=strcat(T,t3)
T=strcat(T,”)”)
T=strcat(T,”*”)
T=strcat(T,T2)
5、 若X和Y是用结点大小为1的单链表表示的串,试设计一个算法找出X中第一个不在Y中出现的字符。
linklist* temp = y;
while (x != NULL) {
while (temp != NULL && x->data != temp->data)
temp = temp->next;
if (temp == NULL)
return x->data;
else {
x = x->next;
temp = y;
}
}
6、 试设计一个算法,在顺序串上实现串的比较运算strcmp(S,T)。
while(*s == *t)
{
if(*s == '\0') return0;
s++;
t++;
}
return *s - *t;
7、 若S和T是用结点大小为1的单链表存储的两个串,试设计一个算法将S中首次与串T匹配的子串逆置。
linklist *s = CREATLIST();
linklist *t = CREATLIST();
linklist *head_t = t;
linklist *temps = s;
linklist *tempt = t;
linklist *p, *m, *n;
for (;;) {
while (temps != NULL && temps->data == tempt->data) {
temps = temps->next;
tempt = tempt->next;
}
if (temps == NULL)
break;
else {
t = t->next;
temps = s;
tempt = t;
}
}
p = head_t;