数据结构典型例题

数据结构典型例题
数据结构典型例题

基本概念典型例题

一、单项选择题

[例6-1]数据结构用集合的观点可以表示为一个二元组DS=(D,R)。其中,D是( ①)的有穷集合,R是D上( ②)的有限集合。

①A.算法B. 数据元素C. 数据操作D. 逻辑结构

②A. 操作B. 映像C. 存储D.关系

解析:由数据结构的集合形式化定义可知,本题答案为:①B;②D。

[例6-2]数据的常用存储结构中不包括( )。

A.顺序存储结构B.线性结构C.索引存储结构D.散列存储结构

解析:数据通常有四种基本的存储方法,即顺序存储方法、链式存储方法、索引存储

方法和散列存储方法。由此可知,本题答案为:B。

[例6-3] 算法指的是( ①),它必须具备( ②)这三个特性。

①A.计算方法B.排序方法C.解决问题的步骤序列D.调度方法

②A.可执行性、可移植性、可扩充性B.可执行性、确定性、有穷性

C.确定性、有穷性、稳定性D.易读性、稳定性、安全性

解析:算法是对特定问题求解步骤的一种描述,是由若于条指令组成的有限序列。它

必须满足以下性质:输人性、输出性、有穷性、确定性、无二义性和可行性。由此可知,本

题答案为:①㈠②B。

[例6-4] 在下面的程序段中,对x的赋值语句的执行频度为( )。

for(i=0;i

for(j=0;j

x=x+l:

A.O(2n) B.O(n) C.O(n2) D.O(1bn)

解析:语句的执行频度即语句重复执行的次数,属于算法的时间复杂度类题目。本题

中对x的赋值语句为一个二重循环的循环体,外层循环循环n次,内层循环也循环n次,

显然此语句的执行次数为n×n=n2次。由此可知,本题答案为:C。

二、填空题

[例6-5]是数据的基本单位,通常由若干个组成,是数据的最小单位。

解析:本题是基本概念题,知识点为数据结构的相关概念。本题答案为:数据元素;数

据项;数据项。

三、应用题

[例6-6] 简述数据结构的定义。

解析:数据结构是指数据元素之间的相互关系,即数据的组织形式。数据结构通常包

括三个方面的内容,分别是数据的逻辑结构、数据的存储结构(物理结构)和在这些数据上

定义的运算。用集合的观点可以把数据结构表示为一个二元组DS=(D,R)。其中,D是数

据元素的有穷集合,R是D上关系的有限集合。

[例6-7]分析以下程序段的时间复杂度。

for(i=0;i

{

x=x+1;//语句②

for(j=0;j<2*n;j++) //语句③

y++;//语句④

}

解析:语句的执行频度指的是语句重复执行的次数。一个算法中所有语句的执行频度之和构成了该算

法的运行时间。在本例算法中,语句①的执行频度是n+l,语句②的执行频度是n,语句③的执行频度是n(2n+2)=2n2-2n,语句④的执行频度是n(2n+1)=2n2+n。该程序段的时间复杂度T(n)=(n+1)+n+(2n2+2n)+(2n2+n)=4n2+5n+1=O(n2)。

实际上,可以用算法中基本操作重复执行的频度作为度量标准,而被视为基本操作的一般是最深层循环内的语句。在上例中,语句④为基本操作,其执行频度为2n2+n,因此,

该算法的时间复杂度T(n)=2n2+n=O(n2)。

[例6-8] 分析以下程序段的时间复杂度。

i=1;

while(i<=m)

i=i*2;

解析:上述算法的基本操作语句是i=i*2,设其执行频度为T(n),则有:2T(n)≤n,即

T(n)≤lbn=O(lbn)。因此,该程序段的时间复杂度为O(lbn)。

线性结构典型例题

一、单项选择题

[例7-1]在数据结构中,与所使用计算机无关的数据叫( ①)结构;链表是一种采用( ②)存储结构存储的线性表;链表适用于( ③)查找;在链表中进行( ④)操作的效率比在线性表中进行该操作的效率高。

①A.存储B.物理C.逻辑D.物理和逻辑

②A.顺序B.网状C.星式D.链式

③A.顺序B.二分法C.顺序及二分法D.随机

④A.二分法查找B.快速查找C.顺序查找D.插入

解析:本题考查的是基本概念。本题答案为:①C;②D;③A;④D。

[例7-2] 链表不具备的特点是( )。

A.插入和删除不需要移动元素B.可随机访问任一结点

C.不必预分配空间D.所需空间与其长度成正比

解析:线性表可随机访问任一结点,而链表必须从第一个数据结点出发逐一查找每个

结点。本题答案为:B。

[例7-3] 不带头结点的单链表head为空的判定条件是( )。

A.head==NULL B.head_>next==NULL

C.head_>next==head D.head!=NULL

解析:在不带头结点的单链表head中,head指向第一个数据结点。空表即该表没有结

点,head==NULL表示该单链表为空。本题答案为:A。

[例7-4] 带头结点的单链表head为空的判定条件是( )。

A.head==NULL B.head—>next==NULL

C.head—> next==head D.head!=NULL

解析:在带头结点的单链表head中,head指向头结点。空表即该表只有头结点,head—>next==NULL 表示该单链表为空。本题答案为:B。

[例7-5] 带头结点的循环单链表head中,head为空的判定条件是( )。

A.head==NULL B.head—>next==NULL

C.head—> next==head D.head!=NULL

解析:在带头结点的循环单链表head中,head指向头结点。空表即该表只有头结点,head—>next==head表示该单链表为空。本题答案为:C。

[例7-6] 线性表采用链式存储时其存储地址( )。

A.必须是连续的B.部分地址必须是连续的

C.一定是不连续的D.连续不连续都可以

解析:链式存储采用动态存储,地址一般不连续。本题答案为:D。

[例7-7] 在双向链表的* p结点前插入新结点*s的操作为( )。

A.p—>prior=s;s—>next=p;p—>prior—>next=s;s—>prior=p—>prior;

B.p—>prior=s;p—>prior—>next=s;s—>next=p;s—>prior=p—>prior;

C.s—>next=p;s—>prior=p—>prior;p—prior=s;p—>prior—>next=s;

D.s—>next=p;s—>prior=p—>prior;p—prior—>next=s;p—>prior=s;

解析:在双向链表的* p结点前插入新结点* s的操作如图7.12所示,图中虚线为所

作的操作,序号为操作顺序。本题答案为:D。

图7.12 双向链表插入结点的过程示意图

(例7-8)若某表最常用的操作是在最后一个结点后插入一个结点和删除第一个结点,则采用( )存储方式最节省运算时间。

A.单链表B.双向链表

C.给出表头指针的循环单链表D.给出尾指针的循环单链表

解析:在链表中插入或删除一个结点,需修改相邻结点的指针域。上述四个选项中,

只有选项D才能从尾指针经过最少的结点来进行题目要求的插入或删除操作。本题答案

为:D。

[例7-9] 若线性表中有2n个元素,算法( )在单链表上实现要比在顺序表上实现效率更高。

A.删除所有值为x的元素B.在最后一个元素的后面插入一个新元素

C.顺序输出前k个元素D.交换其中某两个元素的值

解析:对于选项A,在单链表上和顺序表上实现的时间复杂度都为O(n),但后者要移动大量的元素,因此在单链表上实现效率更高。本题答案为:A。

(例7-10) 在长度为n的( )上,删除第一个元素,其算法复杂度为O(n)。

A.只有表头指针的不带头结点的循环单链表

B.只有尾指针的不带表头结点的循环单链表

C.只有表尾指针的带头结点的循环单链表

D.只有尾指针的带表头结点的循环单链表

解析:本题答案为:A。具体算法如下:

linklist * delfirst(linklist * h)

{

Linklist * p=h;

while(p—> next!=h) //找到表尾结点

p=p—>next;

p—>next=h—> next;

free(h);

returnp一>next;//返回头指针

}

二、填空题

[例7-11] 在单链表中结点* p后插入结点* s的指令序列为;。

解析:在单链表中结点* p后插入结点* s,即将* p 的后继结点变为* s 的后继结点,

* s 则成为* p的后继结点。操作指令序列为:s—>next=p—>next;p—>next=s。

[例7-12]在线性表的链式存储结构中,根据每个结点所含指针的个数,链表可分为和;而根据指针的链接方式,链表又可分为和。

解析:本题答案为:单链表;多重链表;循环链表;普通链表(非循环链表)。

[例7-13] 在单链表中,要删除某一个指定的结点,必须找到该结点的结点。

解析:由单链表的特点可知,删除某一个结点的操作是将其前驱结点的next指针域指

向该结点的后继结点。本题答案为:前驱。

[例7-14] 在一个长度为n 的顺序表中删除第i(0≤i ≤n 一1)个元素,需向前移动 个元素。

解析:需将第i 个元素后的元素依次前移一个位置,总共移动(n-1)-(i+1)+1个元素。本题答案为:n-i-1。

[例7-15] 在一个具有n 个结点的单链表,在 * p 结点后插入一个新结点的时间复杂度是 ;在给定值为x 的结点后插入一个新结点的时间复杂度是 。

解析:在 * p 结点后插入一个新结点 * s 的操作是:s —> next =p —> next ;p —>next =

s ;其时间复杂度为0(1)。

在给定值为x 的结点后插入一个结点,首先要找到该结点,然后再进行插入。找到该

结点的时间复杂度为O(n),插入的时间复杂度为O(1)。本题答案为:O(1);O(n)。

三、应用题

(例7-16) 设A 是一个线性表(a 0,a 1,…,a i ,…,a n-1),采用顺序存储结构,则在等概率情况下平均每插入一个元素需要移动的元素个数是多少?若元素插在a i 和a i+1之间

(0≤i ≤n-1)的概率为1(1)/2

n n n -+,则平均每插入一个元素所需要移动的元素个数是多少?

解析:在等概率情况下,平均每插入一个元素需要移动的元素个数为:

(012)12

n n n ++++=+ 若元素插在a i 和a i+l 之间(0≤i ≤n-1)的概率为

(1)/2n i n n -+,则平均每插入一个元素所需 要移动的元素个数为:

10n i -=∑2222()221(1)1(1)/2(1)3

n i n n n n n n n -+??=+-++=??++ (例7-17) 简述线性表采用顺序存储方式和链式存储方式的优缺点。

解析:顺序表的优点是可以随机访问数据元素,而且不需要额外的空间存储元素间的逻辑关系;缺点是表的大小固定,增减结点需要移动大量元素。链表的优点是增减元素非常方便,只需要修改指针内容;缺点是只能进行顺序访问,另外在每个结点上增加指针域会造成存储空间增大。

[例7-18] 若频繁地对一个线性表进行插入和删除操作,则应采用何种存储结构来存储该线性表?为什么?

解析:应采用链式结构来存储该线性表。采用链式存储结构来存储线性表,在进行插

入和删除操作时的复杂度体现在查找插入或删除结点的前驱结点的操作上,查找过程中平

均移动指针域的次数为表长的一半;而采用顺序存储结构存储线性表,在进行插入和删除

操作时的复杂度则体现在元素的移动上,平均需移动表中的一半元素。因为指针域的移动

操作次数比元素的移动操作次数少得多,所以应采用链式结构来存储该线性表。

(例7—19) (1)写出在双向链表中的结点 * p 前插入一个结点 *s 的语句序列。

(2)写出判断带头结点的双向循环链表L 为空表的条件。

解析:(1)s —>prior =p —>prior ;p —>prior — >next =s ;

s —>next =p ;p —>prior =s ;

(2)(L ==L —>next)&&(L ==L —>prior)

[例7-20] 链表所表示的元素是否是有序的?如果有序,则有序性体现在何处?链表所表示的元素是否一定要在物理上是相邻的?有序表的有序性又如何理解?

解析:链表所表示的元素是有序的,其有序性体现在逻辑有序,即指针有指向。链表所表示的元素在物理上不一定相邻。有序表的有序性不仅在逻辑结构上有序,而且在物理结构上也有序。

四、算法设计题

(例7-21)编写一个算法,将一个带头结点的单链表逆转。要求在原链表空间上进行逆转,即不允许构造新的链表结点;

解析:从单链表的一种构造方法——头插法中可以得知,该方法构造的线性表中结点的顺序与插人次序相反。因此我们可以将表结点从前往后逐个拆下并用头插法插人新表,所构造的单链表即为原表的逆转。

具体算法如下:

linklist * reverse(1inklist * h)

{

linklist * p,*q,*r;

p=h—>next;

h—>next=NULL;//构造空表

while(p!=NULL)

{

q=p;//拆下结点

p=p—> next;

q—>next=h—>next;//用头插法插入

h—>next=q;

}

return h;

}

(例7-22) 已知一个顺序表La的元素按值非递减有序,编写一个算法将元素x插人后保持该表仍然按值非递减有序。

解析:要让插入新元素后的顺序表仍然按值非递减有序,必须把x插入到表中第一个

大于等于x的元素之前。应先在表中找到该位置,然后后移该元素,空出一个位置,再将x

插入。

具体算法如下:

insert(sqlist *La,datatype x) //La为指向顺序表的指针

{

int i=0,j;

while(i<= La—>last) //查找插入位置i

{

if(x<=La—>data[i])

break;

i++;

}

for(j=La—>last+1;j>i;j--) //后移所有大于等于x的元素

La—>data[j]=La—>data[j-1];

La—>data[i]=x;//将x插入

La—>last++;//表长度加1

}

(例7-23)用顺序表A、B表示集合,编写算法求集合A和集合B的交集C(假设A、B表内无重复元素)。’

解析:求C=A∩B,C中元素是A、B中的公共元素。对于表A中的每个元素,在表B中扫描,若有与它相同的元素,则为交集元素,将其放到C中。

具体算法如下:

intersection(sqlist A,sqlist B,sqlist * C)

{

int i,j,k=0;

for(i=0;i<=A.1ast;i++)

{

j=0;

while(j<=B.1ast&& A.dara[i]!=B.data[j]

j++;

if(j<=B.1ast) //表示A.data[i]在B中

C—>data[k++]=A.data[i]

}

C—>last=k—l;//修改表长度

}

[例7-24]编写一个算法,计算在头指针为head的单链表中数据域值为x的结点个数。

解析:先设一计数器n,初值为0。然后遍历链表中的每个结点,每遇到一个结点都需

要判断其数据域值是否为x,如果是,计数器n加1。遍历完成后计数器n的值就是所求的结点数。

具体算法如下:

int count(linklist * head, datatype x)

{

int n=0;

linklist * p;

p = head;

while(p ! = NULL)

{

if(p—> data = = x)

n++;

p=p—>next;

}

return n;

}

(例7-25)用单链表La、Lb表示集合A、B,编写算法求集合A和集合B的差集C,

并用链表Lc表示(假设A、B内无重复元素)。

解析:根据集合运算规则可知,集合A—B中包含所有属于集合A而不属于集合B的

元素。具体做法是:从头到尾扫描单链表La,并判断当前元素是否在单链表Lb中;若不在,则将其插入单链表Lc中。

具体算法如下:

linklist * difference(linklist * La, linklist * Lb)

{

linklist *Lc, * pa, *pb, * s, * r;

pa= La—>next

Lc = (linklist * ) malloc (sizeof (linklist)) ;

r=Lc;

while(pa! = NULL)

{

pb=Lb—> next;

while (phb! = NULL & & pb—> data ! = pa—> data)

pb= pb—>next;

if(pb = = NULL)

{

s= (linklist * )malloe(sizeof(linklist));

s—> data= pa—>data;

r—>next=s;

r—s;

}

pa= pa—>next;

}

r—>next = NULL;

return Lc;

}

(例7-26) 已知两个头指针分别为La和Lb的单链表,它们的元素按值递增有序。编写一算法将两个单链表合并,要求合并后链表仍然递增有序,不允许开辟另外的链表空间。

解析:由于题目要求不开辟另外的链表空间,所以首先以两个链表中的一个头结点为新链表的头结点构造一个空的单链表。从头到尾逐个比较La和Lb表中的元素,将值较小的元素结点链接到新表的末尾,若结点值相同则将其中一个链接到新表的末尾而释放另一个。当La或Lb为空后,把另一个链表余下的结点链接到新表的末尾。

具体算法如下:

linklist * union(linklist * La, linklist * Lb)

{

linklist * pa, * pb, * r;

pa = La—> next;

pb= Lb—>next;

r=La;//以*La为新表头结点,r为新表尾指针

free(Lb); //释放Lb表头结点

while(pa! =NULL && pb! =NULL)

{

if ( pa—> data< pb—> data)

{

r=pa;

pa= pa—>next;

}

else if(pa—>datadata)

{

r—> next = pb;

r=pb;

pb = pb—> next;

r—>next= pa;

}

else //pa->data = = Pb—>data的情况

{

r=pa;//将原La表结点插入,原Lb表结点删除

pa = pa—> next;

s=pb;

pb = pb—>next;

free(s);

}

}

if(pa==NULL) //将Lb表剩余结点链到新表

r—>next=pb;

return La;//返回新表头结点地址

}

(例7-27) 设计——个将循环双链表中结点*p与其后继结点交换位置的算法。解析:本题应充分利用双向链表可对前驱结点和后继结点进行操作的特点。

具体算法如下:

int swap(dlinklist * p)

{

dlinklist * q;

if(p—>next= = p—>prior) //只有一个数据结点,不能交换

return 0;//交换失败

q=p—>next;//q指向* p的后继

p—>next=q—>next;//删除* q

q—>next—>prior= p;

q—>prior= p—>prior;//把*q插入*p前

q—>next=p;

p—>prior—>next=q;

p—>prior=q;

return 1;//交换成功

}

栈和队列

一、单项选择题

[例8-1]在一个具有n个单元的顺序栈中,假设以地址高端作为栈底,以top为栈顶指针,则向栈中压入一个元素时top的变化是( )。

A.top不变B.top=n C.top=top-1 D.top=top+1

解析:本题答案为:C。

(例8-2) 一个栈的进栈序列是a,b,c,d,e,则不可能的出栈序列是( )。

A.edcba B.decba C。dceab D.abcde

解析:栈的特点是先进后出。在选项C中,a、b、c、d进栈,d出栈,c出栈,e进栈,e出栈,此时栈中从栈顶到栈底应该是b、a,不可能a先出栈。本题答案为:C。

[例8-3] 若已知一个栈的进栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,p n,若p l=3,则p2为( )。

A.可能是2 B.不一定是2 C.可能是1 D.一定是1

解析:当p1=3时,表示3最先出栈,前面l、2应该在栈中。此时若出栈,则p2为2;

此时若进栈,则p2可能为3,4,5,…,n的任何一个。本题答案为:A。

[例8-4]若一个栈的输入序列为1,2,3,4,…,n,输出序列的第一个元素是n,则第i个输出元素是( )。

A.n—i B.n—i—1 C.i D.n—i+1

解析:本题答案为:D。

(例8-5) 栈和队列的共同点是( )。

A.都是先进后出B.都是先进先出

C.只允许在表端点处插入和删除元素D.没有共同点

解析:栈和队列都是操作受限的线性表,只允许在表端点处进行插入和删除操作。本

题答案为:C。

(例8-6)向一个栈顶指针为top的链栈中插入一个s所指的结点时,操作语句序列为( )。

A.top—>next=top;B.s—>next=top—>next;top—>next=s;

C.s—>next=top;top=s;D.s—>next=top;top=top—>next;

解析:向链栈中插入一个结点,就是在不带头结点的单链表的表头插入一个结点。本

题答案为:C。

[例8-7] 在解决计算机主机与打印机之间速度不匹配的问题时,通常设置一个打印数据缓冲区,主机将要输出的数据依次写入该缓冲区,而打印机则从该缓冲区中取出数据进行打印。该缓冲区应该是一个( )结构。

A.栈B.队列C.数组D.线性表

解析:本题答案为:B。

(例8-8)一个队列的入队序列是1,2,3,4,则队列的输出序列是( )。

A.4,3,2,1 B.1,2,3,4 C.1,4,3,2 D.4,1,3,2

解析:本题答案为B。

[例8-9]判断一个循环队列Q为满队列的条件是( )。

A.Q一>front= =Q—>rear

B.Q一>front!=Q—>rear

C.Q一>front= =(Q一>rear+1)%MaxSize

D.Q—>front!=(Q—>rear+1)%MaxSize

解析:由循环队列的结构可知,本题答案为:C。

[例8-10]循环队列用数组A[0,MaxSize-1]存放其元素,已知其头尾指针分别是front和rear,则当前

队列元素个数为( )。

A.(rear—front + MaxSize)%MaxSize B.rear—front+1

C.rear—front—l D.rear—front

解析:本题答案为:A。

(例8-11) 在一个链队列中,假设f和r分别是队头指针和队尾指针,则插入s所指

结点的运算是( )。

A.f —>next=s;f=s;B.r—> next=s;r=s;

C.s—> next=r;r=s;D.s—> next=f;f=s;

解析:向链队列插入一个结点即在单链表表尾插入一个结点。本题答案为:B。

二、判断题

[例8-12]栈是一种先进先出的线性结构。

解析:错误。栈是一种先进后出的线性结构。

[例8-13] 栈和队列都是线性表。

解析:正确。栈和队列都是操作受限的线性表。

[例8-14]即使对不含相同元素的同一输入序列进行两组不同的但合法的人栈和出栈组合操作,所得的输出序列也一定相同。

解析:错误。根据栈的特性,不同的人栈和出栈组合操作所得的输出序列是不相同的。

[例8-15]循环队列也存在空间溢出问题。

解析:正确。循环队列的引入只是解决了一般顺序队列的假溢问题,并没有解决溢出

问题。

[例8-16] 循环队列通常用指针来实现队列的头尾相接。

解析:错误。循环队列的首尾相接是假想的,事实上并没有实质上的相接,只是在指针时实现了从最大下标向最小下标的过渡。

三、填空题

[例8-17] 栈的特点是,队列的特点是,栈和队列都是。

解析:本题答案为:先进后出/FILO(或后进先出/LIFO);先进先出/FIFO;操作受限的线性表。

[例8-18] 一个栈的输入序列是:l,2,3,则不可能的栈输出序列是。

解析:在栈的操作中,如果输入序列按递增排序号,则在输出序列中,某一个元素后

所有比它序号小的元素序号肯定是逆序的。本题答案为:3,1,2。

[例8-19]队列是限制了插入操作只能在表的一端,而删除操作只能在表的另一端进行的线性表,其特点是。

解析:本题答案为:先进先出。

(例8-20)若用不带头结点的单链表来表示链栈s,则创建一个空栈所要执行的操作是。

解析:由链栈的运算过程可知,本题答案为:s=NULL。

(例8-21)在链队列Q中,判定其只有一个结点的条件是。

解析:只有一个结点时,队头指针和队尾指针都指向链表头结点。

本题答案为:Q—>front==Q—>rear。

四、应用题

[例8-22]为什么说栈是一种先进后出表?

解析:栈是一种线性表,如果把所有元素都放人栈中再出栈,则最后插入栈中的那个元素总是最先从栈中移出,因此说栈是一种先进后出表。

(例8-23)对于一个栈,按顺序输入A,B,C。如果不限制出栈时机(即栈中元素不必等所有输入元素都进栈再输出),试给出全部可能的输出序列。

解析:本题利用栈的后进先出的特点,有如下几种情况:

(1)A进,A出,B进,B出,C进,C出,产生输出序列ABC。

(2)A进,A出,B进,C进,B出,C出,产生输出序列ACB。

(3)A进,B进,B出,A出,C进,C出,产生输出序列BAC。

(4)A进,B进,C进,C出,B出,A出,产生输出序列CBA。

(5)A进,B进,B出,C进,C出,A出,产生输出序列BCA。

不可能产生的序列为:CAB。

(例8-24)有一字符串次序为-3 * y - a/y^2,试利用栈将该字符串次序改为3y-ay^2/ * -,写出操作步骤。(可用X代表扫描该字符串并顺序取一字符进栈的操作,用S代表从栈中取出一字符加到新字符串尾的出栈操作)

解析:实现上述转换的进、出栈操作如下:

-进3进3出*进y进y出-进-出a进

a出/进y进y出^进^出2进2出/出

*出-出

所以操作步骤为:XXSXXSXSXSXXSXSXSSSS。

(例8-25)什么是顺序队列的上溢现象?什么是假溢现象?解决假溢现象的方法有哪些?

解析:在队列的顺序存储结构中,设队头指针为front,队尾指针为rear,队的容量为

MaxSize。当有元素加入队列时,若rear==MaxSize-1(初始时rear==-1),则发生队列的上溢现象,该元素不能加入队列。

队列的假溢现象是指队列中尚有空余空间,但此时rear==MaxSize-1,元素不能入队。解决队列假溢的方法如下:

(1)建立一个足够大的存储空间,但这样做会造成空间浪费。

(2)采用循环队列方式。原理参照8.2.5中的介绍。

(3)采用平移元素的方法,即每当队列中删除一个元素肘,依次移动队中元素,始终使front==—1。

(例8-26)假设Q[0..11]是一个循环队列,初始状态为front==rear=0,画出做完下列操作后队列的头、尾指针的状态变化情况。若不能人队,请指出其元素,并说明理由。

d,e,b,g,h入队

d,e出队

i,j,k,l,m人队

b出队

n,o,p,q人队

解析:本题入队和出队的变化如图8.7所示。队列没有产生上溢。

五、算法设计题

[例8-27] 设有两个栈S1和S2,都采用顺序结构表示,并且共享一个存储区V[o.. n-1]。为尽量利用空间,减少溢出的可能,现采用栈顶相对、迎面增长的方式存储。试设计公用栈的操作算法。

解析:让两个栈迎面增长,只有相遇时才会溢出。另外,用一个变量i(i=1表示栈l操作,i=2表示栈2操作)来区别S1和S2的操作。

进栈操作算法如下:

int push(datatype V[ ],int top1,int,top2,datatype x,int i)

{

if(i!=1& & i!=2)

return 0;//参数错误

if(topl+1 !=top2)

{

if(i= =1) //S1进栈操作

V[++topl]=x;

else //S2进栈操作

V[++--top2]=x;

}

else

return 0;//溢出

return l;//成功

}

[例8-28]设单链表中存放着n个字符,试设计判断字符是否中心对称的算法。例如,abcba和xyzzyx

是中心对称。

解析:

方法一:将字符串中前一半字符进栈,然后将栈中字符逐个与链表中的后一半字符进行比较。要注意区分字符个数为奇数和偶数的两种情况。字符串不对称时,返回值为0;反之,返回值为1。

int mateh(1inklist * h,int n)

{

linklist * p;

int i=1;

datatype x;

sqstack s;

initstack(&s);//栈初始化

p=h一>next;//p指向链表第一个数据结点

while(i!=n/2+1) //扫描链表前一半

{

push(s,p—>data);//元素进栈

p=p一>next;

i++;

}

if(n%2!=0) //n为奇数

p=p—>next;

while(p!=NULL)

{

x=pop(s);//元素出栈

if(x!=p—>data) //若不相等,则不对称

return 0;

p=p—>next;

}

return 1;//中心对称

}

方法二:将字符串中的全部字符进栈,然后将栈中字符逐个出栈,并与链表中字符从前,往后逐个比较。字符串不对称时,返回值为0;反之,返回值为1。

int match(1inklist * h)

{

linklist * p;

datatype x;

sqstack s;

initstack(&s);//初始化

p=h—>next;//p指向链表第一个数据结点

while(p!=NULL)

{

push(s,p—>data);//元素进栈

p=p—>next;

}

p=h—>next;//P重新指向链表第一个数据结点

while(p!=NULL)

{

x=pop(s);//元素出栈

if(x!=p—>data) //若不相等,则不对称

return 0;

p=p—>next;

}

return 1;//中心对称

}

[例8-29]编写一个算法,利用队列的基本运算返回队列中的最后一个元素。

解析:假设队列为循环顺序队列。建立一个临时队列,将指定队列中所有元素出队并入队到临时队列中,这样指定队列为空,再将临时队列中所有元素出队并入队到指定队列(因为不能破坏原队列结构,所以需要恢复元素),最后一个元素即为所求。具体算法如下:

datatype lastelem (queue * Q)

{

datatype x;

queue tmp Q;

initqueue(& tmp Q)

while(! emty (Q)) //将Q中元素放入tmpQ

{

x=dequeue(Q)

enqueue(&tmpQ,x);

}

while (! empty (& tmpQ)) //将tmpQ中元素恢复回Q

{

x=dequeue ( & tmpQ);

enqueue(Q,x);

}

return x;

}

(例8-30) 假定用一个循环单链表表示队列(循环链队,带头结点),该队列只设一个队尾指针rear,不设队头指针,试编写算法实现下列要求:

(1)向循环链队中插入一个元素x。

(2)从循环链队中删除一个结点。

解析:定义本题队列类型如下:

typedef struct

{

linklist * rear;

} Queue2

(1)队列中人队操作是在队尾进行,即在链尾插入一个新结点。

void enqueue (Queue2 * Q,datatype x)

{

linklist * s;

s=(linklist * )malloe (sizeof (linklist));//建立新结点

s—>datda=x;

s—>next=Q—>rear—>next;//将新结点插入队尾

q—>rear—>next = s;

q—>rear = s;

}

(2)队列中出队操作是在队头进行,即删除链表第一个数据结点。

datatype dequeue (Queue2 * Q)

{

datatype x;

linklist * p;

if (Q—>rear—>next= =Q—>rear) //队列为空

return NULL;

p=Q一>rear一>next一>next;//p指向队头结点

x=p一>data;

Q一>rear一>next一>next=p一>next //删除* p结点

free (p)

return x;//返回原队头元素

}

注意:队列和栈都是线性表,它们是操作受限的线性表。在考虑它们的性质、算法的时候可以结合上一章中有关线性表的内容。

数组

一、单项选择题

[例9-1]下列操作中,( )是数组的基本运算。

A.插入B.删除C.修改D.排序

解析:数组的基本运算只有两种,一种是给定一组下标,存取相应的元素;另一种是

给定一组下标,修改相应数据元素中某个数据项的值。本题答案为:C。

(例9-2) 一维数组和线性表的区别是( )。

A.前者长度固定,后者长度可变B.后者长度固定,前者长度可变

C.两者长度均固定D.两者长度均可变

解析:由数组和线性表的定义可知,数组的长度是固定的,而线性表的长度是可变的。

本题答案是:A。

[例9-3]二维数组A的每个元素是由6个字符组成的字符串,其行下标i=0,1,…,8,列下标j=1,2,…,10。当A按行存储时,元素A[8,5]的起始地址与当A按列存储时的元素( )的起始地址相同(设每个字符占一个字节)。

A.A[8,5] B.A[3,10] C.A[5,8] D.A[0,9]

解析:当A按行存储时,元素A[8,5]前共有(8—0)×(10—1+1)+(5—1)=84个元素。对侯选答案进行类似计算可知,本题答案为:B。

(例9-4) 有一个100×90的稀疏矩阵,有非零元素(整型)10个。设每个整型数占2个字节,则用三元组表表示该矩阵时,所需的字节数为( )。

A.60 B.66 C.18 000 D.33

解析:三元组表由表头和主表两部分组成。表头包括三个整型域,分别表示矩阵的行数、列数和非零元素个数;主表用手存放非零元素三元组,每个三元组由三个域组成,分别表示该元素的行号、列号和值。本题答案为:B。

[例9-5] 若对n阶对称矩阵A以行序为主序方式将其下三角形的元素(包括主对角线上的所有元素)依次存放于一维数组B[0..(n(n+1))/2—1)中,则在B中确定a i,j(i

A.

(1)

2

i i

j

+

+B.

(1)

2

j j

i

-

+C.

(1)

2

i i

j

+

+D.

(1)

2

j j

i

+

+

解析:参考9.2.3节有关对称矩阵的内容可知,本题答案为:D。

二、填空题

(例9-6)三维数组A[c1..d1,c2..d2,c3..d3]共含有个元素。

解析:第一维大小为d1-c l+1,第二维大小为d2-c2+1,第3维大小为d3-c3+1,共有(d l-c1+1)×(d2-c1+1)×(d3-c3+1)个元素。

本题答案为:(d1-c2+1)×(d2-c1+1) ×(d3-c3+1)。

[例9-7]设二维数组A[-20..30,-30..19],每个元素占用4个存储单元,存储起始地址为200。如按行优先顺序存储,则元素A[25][18]的存储地址为;如按列优先顺序存储,则元素A[一18][一25]的存储地址为。

解析:当按行优先顺序存储时,元素A[25][18]的存储地址为:

LOC(A[25][18])=LOC(A[-20][-30])+((25-(-20))×(19-(-30)+1)

+(18-(-30)))×4

=200+9192=9392

当按列优先顺序存储时,元素A[-18][-25]的存储地址为:

LOC(A[-18][-25])=LOC(A[-20][-30])+((-25-(-30))×(30-(-20)+1)

+(-18-(-20))) ×4

=2004+1028=1228

本题答案为:9392;1228。

[例9-8] 将一个10阶对称矩阵A 用压缩存储方式(以行为主序存储下三角,且a 00=1)进行存储,设每个元素占一个地址空间,则a 85的地址为 。

解析:矩阵下标从0开始,以行为主序存储下三角,a 85前有8行,第0行1个元素,第1行2个元素,……,第7行8个元素,共计(1+8)×8/2=36个元素,第8行中a 85前有5个元素。所以,a 85前共有36+5=41个元素,其地址为41+l =42。本题答案为:42。

[例9-9] 一稀疏矩阵有8个非零元素,矩阵元素为整型。现用三元组表方式对其进行压缩存储,假设整型元素占2个存储单元,则该三元组表至少占 个存储单元。

解析:三元组表由表头和主表两部分组成。表头包括三个整型域,分别表示矩阵的行 数、列数和非零元素个数;主表用于存放非零元素三元组,每个三元组由三个域组成,分别表示该元素的行号、列号和值。表头部分占3×2=6个存储单元,主表部分占8×3×2=48 个存储单元,总共占6+48=54个存储单元。本题答案为:54。

三、应用题

[例9-10] 已知A n ×n 为稀疏矩阵,试从空间和时间的角度比较采用两种不同的存储 结构二维数组和三元组表完成求1

0n ii i a -=∑运算的优缺点。

解析:由题目可知,所进行的运算是计算主对角线元素之和。对于采用二维数组方法存储的矩阵,需要n 2个存储单元,但由于可以进行随机存取,即可以随机地访问主对角线上的元素,因此时间效率比较高。采用三元组表方法存储矩阵时是压缩存储,节省了存储空间,但在算法实现上需要从头到尾扫描整个三元组表,因此时间效率相对低一些。

(例9-11) 设给定n 维数组A[c 1..d 1][c 2..d 2)…[c n ..d n ),如果A[c 1][c 2]…[c n ]的存储地址为a ,每个元素占用1个存储单元,求A[i 1][i 2]…[i n ]的存储地址。

解析:若整个数组采用按行优先顺序存储,则A[i 1][i 2]…[i n ]的存储地址为:

LOC(A[i 1][i 2]…[i n ])=a+((i 1-c 1)×(d 2-c 2+1)×…×(d n -c n +1)

+(i 2-c 2)×(d 3-c 3+1)×…×(d n -c n +1)

+(i n -c n ))×l

若整个数组采用按列优先顺序存储,则A[i 1][i 2]…[i n ]的存储地址为:

LOC(A[i 1][i 2]…[i n ])=a+((i n -c n )×(d n-1-c n-1+1)×…×(d 1-c 1+1)

+(i n-1-c n-1)×(d n-2-c n-2+1)×…×(d 1-c 1+1)

+(i 1-c 1))×l

(例 9-12) 设上三角矩阵A n ×n ,将其上三角元素逐行存于数组B[m]中,使得B[k]=a ij ,且k=f 1(i )+f 2(j )+c 。试推导出函数f 1(i )、f 2(j )和常数C 。

解析:由前面内容的分析可得k 和i 、j 之间的关系为:

(21)2(1)2i n i k n n -+???=?+??? 当i ≤j 时,有

2111f (1)=22

n i i ??-- ??? 2f (j)=j

+j-i 当i ≤j 时 当i>j 时,存放常数c

C=0

当i>j 时,有

12f (i)=f (j)=0

(1)2

n n C +=

四、算法设计题

(例9—13) 已知一个n ×n 矩阵B 按行优先顺序存储在一个一维数组A[0..n ×n 一1) 中,试给出一个算法将原矩阵转置后仍存于数组A 中。

解析:矩阵转置是将矩阵中第i 行第j 列的元素与第j 行第i 列的元素位置互换。因此, 先确定矩阵与一维数组的映射关系:b i ,j 在一维数组A 中的下标为i ×n+j ,b i ,j 在一维数组A 中的下标为j ×n+i 。具体算法如下:

void trans ( datatype A[],int n)

{

int i ,j ;

datatype temp ;

for(i=0;i

for(j =0;j

{

temp=A[i * n+1];

A[i * n+j]=A[j * n+i];

A[j * n+i]=temp ;

}

}

(例9-14) 假设稀疏矩阵A 采用三元组表表示,试编写一个算法求其转置矩阵B ,要求B 也用三元组表表示。

解析:三元组表表示要求按行的顺序存放,所有转置过程不能直接将行下标和列下标 转换,还必须使得转置后矩阵按顺序存放。因此,首先在A 中找出第一列中的所有元素 (即B 中第一行),并把它们依次存放在转置矩阵B 的三元组表中;然后依次找出第二列中的所有元素,把它们依次存放在三元组表B 中;最后按此方法逐列进行,直到第n 列的操作完成。值得注意的是,除了各元素的行号列号需要互换外,表头部分的行数列数也应该互换。具体算法如下:

void transmatrix (smatrix * A ,smatrix * B)

{

int p ,k ,col ;

B —>m=A —>n ; //B 的行数为A 的列数

B —>n=A —>m ; //B 的列数为A 的行数

B —>t=A —>t ; //转置前后非零元素个数不变

if(B —>t!=0) //非0矩阵

{

k=0; //B 表元素计数器,作当前放置元素指针

for(col=0;coln ;col++)

for(p =0;pt ;p++)

if(A —>data[p].j ==co1)

{

B—>data[k].i=A—>data[p].j;

B—>data[k].j=A—>data[p].i

B—>data[k].v=A—>data[p].v;

K++

}

}

}

数据结构经典例题

数据结构例题(及答案) 项目一习题(答案) 一选择题 1. 算法的计算量的大小称为计算的(B )。 A( 效率 B. 复杂性 C. 现实性 D. 难度 2.算法的时间复杂度取决于(C ) A(问题的规模 B. 待处理数据的初态 C. A和B 3(从逻辑上可以把数据结构分为(C )两大类。 A(动态结构、静态结构 B(顺序结构、链式结构 C(线性结构、非线性结构 D(初等结构、构造型结构 4(连续存储设计时,存储单元的地址(A )。 A(一定连续 B(一定不连续 C(不一定连续 D(部分连续,部分不连续 5. 以下属于逻辑结构的是(C )。 A(顺序表 B. 哈希表 C.有序表 D. 单链表 二、判断题 1. 数据元素是数据的最小单位。(×) 2. 记录是数据处理的最小单位。(×) 3. 数据的逻辑结构是指数据的各数据项之间的逻辑关系;(×) 4(程序一定是算法。(×) 5. 在顺序存储结构中,有时也存储数据结构中元素之间的关系。(×) 6. 顺序存储方式的优点是存储密度大,且插入、删除运算效率高。(×) 7. 数据结构的基本操作的设置的最重要的准则是,实现应用程序与存储结构的独立。(?)

8. 数据的逻辑结构说明数据元素之间的顺序关系,它依赖于计算机的储存结构. (×) 三、填空 1(数据的物理结构包括数据元素的表示和数据元素间关系的表示。 2. 对于给定的n个元素,可以构造出的逻辑结构有集合,线性结构,树形 结构,图状结构或网状结构四种。 3(数据的逻辑结构是指数据的组织形式,即数据元素之间逻辑关系的总体。而 逻辑关系是指数据元素之间的关联方式或称“邻接关系”。 4(一个数据结构在计算机中表示(又称映像) 称为存储结构。 5(抽象数据类型的定义仅取决于它的一组逻辑特性,而与在计算机内部如何表 示和实现无关,即不论其内部结构如何变化,只要它的数学特性不变,都不影响 其外部使用。 6(数据结构中评价算法的两个重要指标是算法的时间复杂度和空间复杂度。 7. 数据结构是研讨数据的逻辑结构和物理结构,以及它们之间的相互 关系,并对与这种结构定义相应的操作(运算),设计出相应的算法。 ( 一个算法具有5个特性: 有穷性、确定性、可行性,有零个或多个输入、 有一个或多个输8 出。 四、应用题 1. 1. 数据结构是一门研究什么内容的学科, 答:数据结构是一门研究在非数值计算的程序设计问题中,计算机的操作对象 及对象间的关系和施加于对象的操作等的学科 2. 2. 数据元素之间的关系在计算机中有几种表示方法,各有什么特点, 答:四 种表示方法

经典数据结构面试题(含答案)

栈和队列的共同特点是__________________________ .栈通常采用的两种存储结构是______________________ .用链表表示线性表的优点是_______________________ 8.在单链表中,增加头结点的目的是___________________ 9.循环链表的主要优点是________________________- 12.线性表的顺序存储结构和线性表的链式存储结构分别是 __________________________ 13.树是结点的集合,它的根结点数目是_____________________ 14.在深度为5的满二叉树中,叶子结点的个数为_______________ 15.具有3个结点的二叉树有(_____________________ 16.设一棵二叉树中有3个叶子结点,有8个度为1的结点,则该二叉树中总的结点数为____________________ 17.已知二叉树后序遍历序列是dabec,中序遍历序列是debac,它的前序遍历序列是 ____________________________ 18.已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历为______________________ 19.若某二叉树的前序遍历访问顺序是abdgcefh,中序遍历访问顺序是dgbaechf,则其后序遍历的结点访问顺序是_______________________ 20.数据库保护分为:安全性控制、完整性控制、并发性控制和数据的恢复。 在计算机中,算法是指_______________________ 算法一般都可以用哪几种控制结构组合而成_____________________ .算法的时间复杂度是指______________________ 5. 算法的空间复杂度是指__________________________ 6. 算法分析的目的是__________________________

《数据结构》实验报告——排序.docx

《数据结构》实验报告排序实验题目: 输入十个数,从插入排序,快速排序,选择排序三类算法中各选一种编程实现。 实验所使用的数据结构内容及编程思路: 1. 插入排序:直接插入排序的基本操作是,将一个记录到已排好序的有序表中,从而得到一个新的,记录增一得有序表。 一般情况下,第i 趟直接插入排序的操作为:在含有i-1 个记录的有序子序列r[1..i-1 ]中插入一个记录r[i ]后,变成含有i 个记录的有序子序列r[1..i ];并且,和顺序查找类似,为了在查找插入位置的过程中避免数组下标出界,在r [0]处设置哨兵。在自i-1 起往前搜索的过程中,可以同时后移记录。整个排序过程为进行n-1 趟插入,即:先将序列中的第一个记录看成是一个有序的子序列,然后从第2 个记录起逐个进行插入,直至整个序列变成按关键字非递减有序序列为止。 2. 快速排序:基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。 假设待排序的序列为{L.r[s] ,L.r[s+1],…L.r[t]}, 首先任意选取一个记录 (通常可选第一个记录L.r[s])作为枢轴(或支点)(PiVOt ),然后按下述原则重新排列其余记录:将所有关键字较它小的记录都安置在它的位置之前,将所有关键字较大的记录都安置在它的位置之后。由此可以该“枢轴”记录最后所罗的位置i 作为界线,将序列{L.r[s] ,… ,L.r[t]} 分割成两个子序列{L.r[i+1],L.[i+2], …,L.r[t]}。这个过程称为一趟快速排序,或一次划分。 一趟快速排序的具体做法是:附设两个指针lOw 和high ,他们的初值分别为lOw 和high ,设枢轴记录的关键字为PiVOtkey ,则首先从high 所指位置起向前搜索找到第一个关键字小于PiVOtkey 的记录和枢轴记录互相交换,然后从lOw 所指位置起向后搜索,找到第一个关键字大于PiVOtkey 的记录和枢轴记录互相 交换,重复这两不直至low=high 为止。 具体实现上述算法是,每交换一对记录需进行3 次记录移动(赋值)的操作。而实际上,

数据结构模拟卷(含答案)经典习题培训讲学

数据结构模拟卷(含答案)经典习题

练习题 一、单项选择题 1. 若将数据结构形式定义为二元组(K,R),其中K是数据元素的有限集合,则R是K上( ) A. 操作的有限集合 B. 映象的有限集合 C. 类型的有限集合 D. 关系的有限集合 2. 在长度为n的顺序表中删除第i个元素(1≤i≤n)时,元素移动的次数为( ) A. n-i+1 B. i C. i+1 D. n-i 3. 若不带头结点的单链表的指针为head,则该链表为空的判定条件是( ) A. head==NULL B. head->next==NULL C. head!=NULL D. head->next==head 4. 引起循环队列队头位置发生变化的操作是( ) A. 出队 B. 入队 C. 取队头元素 D. 取队尾元素 5. 若进栈序列为1,2,3,4,5,6,且进栈和出栈可以穿插进行,则不.可能出现的出栈序列是( ) A. 2,4,3,1,5,6 B. 3,2,4,1,6,5 C. 4,3,2,1,5,6 D. 2,3,5,1,6,4

6. 字符串通常采用的两种存储方式是( ) A. 散列存储和索引存储 B. 索引存储和链式存储 C. 顺序存储和链式存储 D. 散列存储和顺序存储 7. 数据结构是() A.一种数据类型 B.数据的存储结构 C.一组性质相同的数据元素的集合 D.相互之间存在一种或多种特定关系的数据元素的集合 8. 算法分析的目的是() A.辨别数据结构的合理性 B.评价算法的效率 C.研究算法中输入与输出的关系 D.鉴别算法的可读性 9. 在线性表的下列运算中,不.改变数据元素之间结构关系的运算是 () A.插入B.删除 C.排序D.定位10. 下列图示的顺序存储结构表示的二叉树是( )

数据结构课后习题及解析第二章

第二章习题 1.描述以下三个概念的区别:头指针,头结点,首元素结点。 2.填空: (1)在顺序表中插入或删除一个元素,需要平均移动元素,具体移动的元素个数与有关。 (2)在顺序表中,逻辑上相邻的元素,其物理位置相邻。在单链表中,逻辑上相邻的元素,其物理位置相邻。 (3)在带头结点的非空单链表中,头结点的存储位置由指示,首元素结点的存储位置由指示,除首元素结点外,其它任一元素结点的存储位置由指示。3.已知L是无表头结点的单链表,且P结点既不是首元素结点,也不是尾元素结点。按要求从下列语句中选择合适的语句序列。 a. 在P结点后插入S结点的语句序列是:。 b. 在P结点前插入S结点的语句序列是:。 c. 在表首插入S结点的语句序列是:。 d. 在表尾插入S结点的语句序列是:。 供选择的语句有: (1)P->next=S; (2)P->next= P->next->next; (3)P->next= S->next; (4)S->next= P->next; (5)S->next= L; (6)S->next= NULL; (7)Q= P; (8)while(P->next!=Q) P=P->next; (9)while(P->next!=NULL) P=P->next; (10)P= Q; (11)P= L; (12)L= S; (13)L= P; 4.设线性表存于a(1:arrsize)的前elenum个分量中且递增有序。试写一算法,将X插入到线性表的适当位置上,以保持线性表的有序性。 5.写一算法,从顺序表中删除自第i个元素开始的k个元素。 6.已知线性表中的元素(整数)以值递增有序排列,并以单链表作存储结构。试写一高效算法,删除表中所有大于mink且小于maxk的元素(若表中存在这样的元素),分析你的算法的时间复杂度(注意:mink和maxk是给定的两个参变量,它们的值为任意的整数)。 7.试分别以不同的存储结构实现线性表的就地逆置算法,即在原表的存储空间将线性表(a1, a2..., an)逆置为(an, an-1,..., a1)。 (1)以一维数组作存储结构,设线性表存于a(1:arrsize)的前elenum个分量中。 (2)以单链表作存储结构。 8.假设两个按元素值递增有序排列的线性表A和B,均以单链表作为存储结构,请编写算法,将A表和B表归并成一个按元素值递减有序排列的线性表C,并要求利用原表(即A 表和B表的)结点空间存放表C。

大数据结构经典复习题(仅供参考)

一、选择题(20分) 1.下面关于线性表的叙述错误的是(D )。 (A) 线性表采用顺序存储必须占用一片连续的存储空间 (B) 线性表采用链式存储不必占用一片连续的存储空间 (C) 线性表采用链式存储便于插入和删除操作的实现 (D) 线性表采用顺序存储便于插入和删除操作的实现 2.设某棵二叉树的中序遍历序列为ABCD,前序遍历序列为CABD,则后序遍历该二叉树得到序列为(A )。 (A) BADC (B) BCDA (C) CDAB (D) CBDA 3.设某棵二叉树中有2000个结点,则该二叉树的最小高度为(C )。 (A) 9 (B) 10 (C) 11 (D) 12 4.设二叉排序树中有n个结点,则在二叉排序树的平均平均查找长度为(B )。 (A) O(1) (B) O(log2n) (C) (D) O(n2) 5.设有5000个待排序的记录关键字,如果需要用最快的方法选出其中最小的10个记录关键字,则用下列(B )方法可以达到此目的。 (A) 快速排序(B) 堆排序(C) 归并排序(D) 插入排序 第9小题分析:9快速排序、归并排序和插入排序必须等到整个排序结束后才能够求出最小的10个数,而堆排序只需要在初始堆的基础上再进行10次筛选即可,每次筛选的时间复杂度为O(log2n)。 6.下列四种排序中(D )的空间复杂度最大。 (A) 插入排序(B) 冒泡排序(C) 堆排序(D) 归并排序

7.设一维数组中有n个数组元素,则读取第i个数组元素的平均时间复杂度为(C )。 (A) O(n) (B) O(nlog2n) (C) O(1) (D) O(n2) 8.设一棵二叉树的深度为k,则该二叉树中最多有(D )个结点。 (A) 2k-1 (B) 2k(C) 2k-1(D) 2k-1 9.在二叉排序树中插入一个结点的时间复杂度为(B )。 (A) O(1) (B) O(n) (C) O(log2n) (D) O(n2) 10.设用链表作为栈的存储结构则退栈操作(B )。 (A) 必须判别栈是否为满(B) 必须判别栈是否为空 (C) 判别栈元素的类型(D) 对栈不作任何判别 11.下列四种排序中(A )的空间复杂度最大。 (A) 快速排序(B) 冒泡排序(C) 希尔排序(D) 堆 12.设某二叉树中度数为0的结点数为N0,度数为1的结点数为N l,度数为2的结点数为N2,则下列等式成立的是(C )。 (A) N0=N1+1 (B) N0=N l+N2(C) N0=N2+1 (D) N0=2N1+l 13.设有序顺序表中有n个数据元素,则利用二分查找法查找数据元素X的最多比较次数不 超过(A )。 (A) log2n+1 (B) log2n-1 (C) log2n (D) log2(n+1) 14.数据的最小单位是(A )。 (A) 数据项(B) 数据类型(C) 数据元素(D) 数据变量 15.设一个有序的单链表中有n个结点,现要求插入一个新结点后使得单链表仍然保持有序,则该操作的时间复杂度为(D )。 (A) O(log2n) (B) O(1) (C) O(n2) (D) O(n)

数据结构实验八内部排序

实验八内部排序 一、实验目的 1、掌握内部排序的基本算法; 2、分析比较内部排序算法的效率。 二、实验内容和要求 1. 运行下面程序: #include #include #define MAX 50 int slist[MAX]; /*待排序序列*/ void insertSort(int list[], int n); void createList(int list[], int *n); void printList(int list[], int n); void heapAdjust(int list[], int u, int v); void heapSort(int list[], int n); /*直接插入排序*/ void insertSort(int list[], int n) { int i = 0, j = 0, node = 0, count = 1; printf("对序列进行直接插入排序:\n"); printf("初始序列为:\n"); printList(list, n); for(i = 1; i < n; i++) { node = list[i]; j = i - 1; while(j >= 0 && node < list[j]) { list[j+1] = list[j]; --j; } list[j+1] = node; printf("第%d次排序结果:\n", count++); printList(list, n); } } /*堆排序*/ void heapAdjust(int list[], int u, int v)

数据结构模拟卷(含答案)经典习题

练习题 一、单项选择题 1. 若将数据结构形式定义为二元组(K,R),其中K是数据元素的有限集合,则R是K上( ) A. 操作的有限集合 B. 映象的有限集合 C. 类型的有限集合 D. 关系的有限集合 2. 在长度为n的顺序表中删除第i个元素(1≤i≤n)时,元素移动的次数为( ) A. n-i+1 B. i C. i+1 D. n-i 3. 若不带头结点的单链表的指针为head,则该链表为空的判定条件是( ) A. head==NULL B. head->next==NULL C. head!=NULL D. head->next==head 4. 引起循环队列队头位置发生变化的操作是( ) A. 出队 B. 入队 C. 取队头元素 D. 取队尾元素 5. 若进栈序列为1,2,3,4,5,6,且进栈和出栈可以穿插进行,则不.可能出现的出栈序列是( ) A. 2,4,3,1,5,6 B. 3,2,4,1,6,5 C. 4,3,2,1,5,6 D. 2,3,5,1,6,4 1

6. 字符串通常采用的两种存储方式是( ) A. 散列存储和索引存储 B. 索引存储和链式存储 C. 顺序存储和链式存储 D. 散列存储和顺序存储 7. 数据结构是() A.一种数据类型 B.数据的存储结构 C.一组性质相同的数据元素的集合 D.相互之间存在一种或多种特定关系的数据元素的集合 8. 算法分析的目的是() A.辨别数据结构的合理性 B.评价算法的效率 C.研究算法中输入与输出的关系 D.鉴别算法的可读性 9. 在线性表的下列运算中,不.改变数据元素之间结构关系的运算是 () A.插入B.删除 C.排序D.定位 10. 下列图示的顺序存储结构表示的二叉树是( ) 2

数据结构经典例题

数据结构经典例题 1.设计一个算法将L拆分成两个带头节点的单链表L1和L2。 void split(LinkList *&L,LinkList *&L1,LinkList *&L2) { LinkList *p=L->next,*q,*r1; //p指向第1个数据节点 L1=L; //L1利用原来L的头节点 r1=L1; //r1始终指向L1的尾节点 L2=(LinkList *)malloc(sizeof(LinkList));//创建L2的头节点 L2->next=NULL; //置L2的指针域为NULL while (p!=NULL) { r1->next=p; //采用尾插法将*p(data值为ai)插入L1中 r1=p; p=p->next; //p移向下一个节点(data值为bi) q=p->next; //由于头插法修改p的next域,故用q保存*p的后继节点 p->next=L2->next; //采用头插法将*p插入L2中 L2->next=p; p=q; //p重新指向ai+1的节点 } r1->next=NULL; //尾节点next置空 } 2.查找链表中倒数第k个位置上的节点(k为正整数)。若查找成功,算法输出该节点的data域的值,并返回1;否则,只返回0。 typedef struct LNode {int data; struct LNode *link; } *LinkList; int Searchk(LinkList list,int k) { LinkList p,q; int count=0; p=q=list->link; while (p!=NULL) { if (countlink; p=p->link; } if (count

数据结构实验五-查找与排序的实现

实验报告 课程名称数据结构实验名称查找与排序的实现 系别专业班级指导教师11 学号实验日期实验成绩 一、实验目的 (1)掌握交换排序算法(冒泡排序)的基本思想; (2)掌握交换排序算法(冒泡排序)的实现方法; (3)掌握折半查找算法的基本思想; (4)掌握折半查找算法的实现方法; 二、实验内容 1.对同一组数据分别进行冒泡排序,输出排序结果。要求: 1)设计三种输入数据序列:正序、反序、无序 2)修改程序: a)将序列采用手工输入的方式输入 b)增加记录比较次数、移动次数的变量并输出其值,分析三种序列状态的算法时间复杂 性 2.对给定的有序查找集合,通过折半查找与给定值k相等的元素。 3.在冒泡算法中若设置一个变量lastExchangeIndex来标记每趟排序时经过交换的最后位置, 算法如何改进? 三、设计与编码 1.本实验用到的理论知识 2.算法设计

3.编码 package sort_search; import java.util.Scanner; public class Sort_Search { //冒泡排序算法 public void BubbleSort(int r[]){ int temp; int count=0,move=0; boolean flag=true; for(int i=1;ir[j+1]){ temp=r[j]; r[j]=r[j+1]; r[j+1]=temp; move++; flag=true; } } } System.out.println("排序后的数组为:"); for(int i=0;i

经典数据结构上机题_答案解析

数据结构上机实验题目 实验一线性表的顺序存储结构 实验学时 2学时 背景知识:顺序表的插入、删除及应用。 目的要求: 1.掌握顺序存储结构的特点。 2.掌握顺序存储结构的常见算法。 实验容 1.输入一组整型元素序列,建立顺序表。 2.实现该顺序表的遍历。 3.在该顺序表中进行顺序查找某一元素,查找成功返回1,否则返回0。4.判断该顺序表中元素是否对称,对称返回1,否则返回0。 5.实现把该表中所有奇数排在偶数之前,即表的前面为奇数,后面为偶数。 6.输入整型元素序列利用有序表插入算法建立一个有序表。 7.利用算法6建立两个非递减有序表并把它们合并成一个非递减有序表。 8. 利用该顺序结构实现循环队列的入队、出队操作。 8.编写一个主函数,调试上述算法。 #include #include

#define OVERFLOW 0 #define MAXSIZE 100 typedef int ElemType; typedef struct list {ElemType elem[MAXSIZE]; int length; }Sqlist; void Creatlist(Sqlist &L) {int i; printf("请输入顺序表的长度:"); //输入一组整型元素序列,建立一个顺序表。 scanf("%d",&L.length); for(i=0;i

数据结构例题解析(1)

I Single Choice(10 points) 1. ( a )For the following program fragment the running time(Big-Oh) is . i = 0; s = 0; while(s <( 5*n*n + 2)) { i++; s = s + i; } a. O(n) b. O(n2) c. O(n1/2) d. O(n3) 2. ( c )Which is non-linear data structure_____. a. queue c. tree d. sequence list 3.( b )The worst-time for removing an element from a sequence list (Big-Oh) is . a. O(1) b. O(n) c. O(n2) d. O(n3) 4.( d )In a circular queue we can distinguish(区分) empty queues from full queues by .

a. using a gap in the array b. incrementing queue positions by 2 instead of 1 a count of the number of elements d. a and c 5.( b )A recursive function can cause an infinite sequence of function calls if . a.the problem size is halved at each step b.the termination condition is missing c.no useful incremental computation is done in each step d.the problem size is positive 6.( c )The full binary tree with height 4 has nodes. a. 15 b. 16 7. ( b )Searching in an unsorted list can be made faster by using . a.binary search

数据结构典型例题

基本概念典型例题 一、单项选择题 [例6-1]数据结构用集合的观点可以表示为一个二元组DS=(D,R)。其中,D是( ①)的有穷集合,R是D上( ②)的有限集合。 ①A.算法B. 数据元素C. 数据操作D. 逻辑结构 ②A. 操作B. 映像C. 存储D.关系 解析:由数据结构的集合形式化定义可知,本题答案为:①B;②D。 [例6-2]数据的常用存储结构中不包括( )。 A.顺序存储结构B.线性结构C.索引存储结构D.散列存储结构 解析:数据通常有四种基本的存储方法,即顺序存储方法、链式存储方法、索引存储 方法和散列存储方法。由此可知,本题答案为:B。 [例6-3] 算法指的是( ①),它必须具备( ②)这三个特性。 ①A.计算方法B.排序方法C.解决问题的步骤序列D.调度方法 ②A.可执行性、可移植性、可扩充性B.可执行性、确定性、有穷性 C.确定性、有穷性、稳定性D.易读性、稳定性、安全性 解析:算法是对特定问题求解步骤的一种描述,是由若于条指令组成的有限序列。它 必须满足以下性质:输人性、输出性、有穷性、确定性、无二义性和可行性。由此可知,本 题答案为:①㈠②B。 [例6-4] 在下面的程序段中,对x的赋值语句的执行频度为( )。 for(i=0;i

数据结构经典题目c语言代码

《数据结构》课程设计题目 (程序实现采用C语言) 题目1:猴子选王(学时:3) 一堆猴子都有编号,编号是1,2,3 ...m,这群猴子(m个)按照1-m的顺序围坐一圈,从第1开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。 要求:m及n要求从键盘输入,存储方式采用向量及链表两种方式实现该问题求解。 //链表 #include #include // 链表节点 typedef struct _RingNode { int pos; struct _RingNode *next; }RingNode, *RingNodePtr; // 创建约瑟夫环,pHead:链表头指针,count:链表元素个数 void CreateRing(RingNodePtr pHead, int count) { RingNodePtr pCurr = NULL, pPrev = NULL; int i = 1; pPrev = pHead; while(--count > 0)

{ pCurr = (RingNodePtr)malloc(sizeof(RingNode)); i++; pCurr->pos = i; pPrev->next = pCurr; pPrev = pCurr; } pCurr->next = pHead; // 构成环状链表 } void KickFromRing(RingNodePtr pHead, int n) { RingNodePtr pCurr, pPrev; int i = 1; // 计数 pCurr = pPrev = pHead; while(pCurr != NULL) { if (i == n) { // 踢出环 printf("\n%d", pCurr->pos); // 显示出圈循序 pPrev->next = pCurr->next; free(pCurr); pCurr = pPrev->next; i = 1; } pPrev = pCurr;

数据结构第一章课后习题与答案

第 1 章 绪 论 (2005-07-14) - 第 1 章 绪 论 课后习题讲解 1. 填空 ⑴( )是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。 【解答】数据元素 ⑵( )是数据的最小单位,( )是讨论数据结构时涉及的最小数据单位。 【解答】数据项,数据元素 【分析】数据结构指的是数据元素以及数据元素之间的关系。 ⑶ 从逻辑关系上讲,数据结构主要分为( )、( )、( )和( )。 【解答】集合,线性结构,树结构,图结构 ⑷ 数据的存储结构主要有( )和( )两种基本方法,不论哪种存储结构,都要存储两方面的内容:( )和()。 【解答】顺序存储结构,链接存储结构,数据元素,数据元素之间的关系 ⑸ 算法具有五个特性,分别是( )、( )、( )、( )、( )。 【解答】有零个或多个输入,有一个或多个输出,有穷性,确定性,可行性 ⑹ 算法的描述方法通常有( )、( )、( )和( )四种,其中,( )被称为算法语言。 【解答】自然语言,程序设计语言,流程图,伪代码,伪代码 ⑺ 在一般情况下,一个算法的时间复杂度是( )的函数。 【解答】问题规模 ⑻ 设待处理问题的规模为n,若一个算法的时间复杂度为一个常数,则表示成数量级的形式为( ),若为 n*log25n,则表示成数量级的形式为( )。 【解答】Ο(1),Ο(nlog2n) 【分析】用大O记号表示算法的时间复杂度,需要将低次幂去掉,将最高次幂的系数去掉。

2. 选择题 ⑴ 顺序存储结构中数据元素之间的逻辑关系是由( )表示的,链接存储结构中的数据元素之间的逻辑关系是由( )表示的。 A 线性结构 B 非线性结构 C 存储位置 D 指针 【解答】C,D 【分析】顺序存储结构就是用一维数组存储数据结构中的数据元素,其逻辑关系由存储位置(即元素在数组中的下标)表示;链接存储结构中一个数据元素对应链表中的一个结点,元素之间的逻辑关系由结点中的指针表示。 ⑵ 假设有如下遗产继承规则:丈夫和妻子可以相互继承遗产;子女可以继承父亲或母亲的遗产;子女间不能相互继承。则表示该遗产继承关系的最合适的数据结构应该是( )。 A 树 B 图 C 线性表 D 集合 【解答】B 【分析】将丈夫、妻子和子女分别作为数据元素,根据题意画出逻辑结构图。 ⑶ 算法指的是( )。 A 对特定问题求解步骤的一种描述,是指令的有限序列。 B 计算机程序 C 解决问题的计算方法 D 数据处理 【解答】A 【分析】计算机程序是对算法的具体实现;简单地说,算法是解决问题的方法;数据处理是通过算法完成的。所以,只有A是算法的准确定义。 ⑷ 下面( )不是算法所必须具备的特性。 A 有穷性 B 确切性 C 高效性 D 可行性 【解答】C 【分析】高效性是好算法应具备的特性。 ⑸ 算法分析的目的是( ),算法分析的两个主要方面是( )。 A 找出数据结构的合理性 B 研究算法中输入和输出的关系 C 分析算法的效率以求改进 D 分析算法的易读性和文档性 E 空间性能和时间性能 F 正确性和简明性 G 可读性和文档性 H 数据复杂性和程序复杂性

数据结构经典算法试题

1.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。【北京大学1998 三、1 (5分)】 LinkedList Union(LinkedList la,lb) { pa=la->next; pb=lb->next; la->next=null; while(pa!=null && pb!=null) ∥当两链表均不为空时作 if(pa->data<=pb->data) { r=pa->next; pa->next=la->next; ∥将pa结点链于结果表中,同时逆置。 la->next=pa; pa=r; } else {r=pb->next; pb->next=la->next; ∥将pb结点链于结果表中,同时逆置。 la->next=pb; pb=r; } 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; } }

1)设有两个无头结点的单链表,头指针分别为ha,hb,链中有数据域data,链域next,两链表的数据都按递增序存放,现要求将hb表归到ha表中,且归并后ha仍递增序,归并中ha表中已有的数据若hb中也有,则hb中的数据不归并到ha中,hb的链表在算法中不允许破坏。【南京理工大学1997 四、3(15分)】 LinkedList Union(LinkedList ha, hb)∥ha和hb是两个无头结点的数据域值递增有序的单链 {LinkedList 表,本算法将hb中并不出现在ha中的数据合并到ha中,合并中不能破坏hb链表。 la; la=(LinkedList)malloc(sizeof(LNode)); la->next=ha; pa=ha; pb=hb; pre=la; while(pa&&pb) if(pa->datadata)∥处理ha中数据 {pre->next=pa;pre=pa;pa=pa->next;} else if(pa->data>pb->data)∥处理hb中数据。 {r=(LinkedList)malloc(sizeof(LNode)); r->data=pb->data; pre->next=r; pre=r; pb=pb->next;} Else∥处理pa- >data=pb->data; {pre->next=pa; pre=pa; pa=pa->next;∥两结点数据相等时,只将ha的数据链入。 pb=pb->next; } if(pa!=null)pre->next=pa;∥将两链表中剩余部分链入结果链表。 else pre->next=pb; free(la); }

数据结构实验快速排序汇编

实验报告实验名称排序 课程名称数据结构与算法实验 | | 专业班级:信息安全 学号: 姓名:

一、实验目的 掌握快速排序 二、实验内容 1、快速排序 编写程序,实现快速排序。从键盘上输入10个整数,存放在数组中,然后用快速排序法对其从小到大进行排序,并输出排序结果。 2、堆排序 编写程序,实现堆排序。从键盘上输入10个整数,存放在数组中,然后用堆排序法对其从小到大进行排序,并输出排序结果。 三、主要算法与结构 //快速排序 int QuickSort(int a[],int l,int r) { int pivot; //枢轴 int i=l; int j=r; int tmp; pivot=a[(l+r)/2];//取数组中间的数为枢轴 do { while (a[i]pivot) j--; // j左移 if (i<=j) { tmp=a[i]; a[i]=a[j]; a[j]=tmp; //交换a[i]和a[j] i++; j--; } } //堆排序 void sift (int a[],int size ,int p) { int tmp= a[p]; int child=2*p+1; while(child

child++; if(tmp=0;i--) sift(a, n,i); for( i=n-1;i>0;i--) { tmp=a[0]; a[0]=a[i]; a[i]=tmp; sift(a, i,0); } } 四、实验代码 //快速排序 #include #define MAX 10 int QuickSort(int a[],int l,int r) { int pivot; //枢轴 int i=l; int j=r; int tmp; pivot=a[(l+r)/2];//取数组中间的数为枢轴 do { while (a[i]pivot) j--; // j左移 if (i<=j) { tmp=a[i]; a[i]=a[j]; a[j]=tmp; //交换a[i]和a[j] i++; j--;

数据结构课后习题详解(超完整,超经典)

第1章 绪论 1.1 简述下列术语:数据,数据元素、数据对象、数据结构、存储结构、数据类型和抽象数据类型。 解:数据是对客观事物的符号表示。在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。 数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。 数据对象是性质相同的数据元素的集合,是数据的一个子集。 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 存储结构是数据结构在计算机中的表示。 数据类型是一个值的集合和定义在这个值集上的一组操作的总称。 抽象数据类型是指一个数学模型以及定义在该模型上的一组操作。是对一般数据类型的扩展。 1.2 试描述数据结构和抽象数据类型的概念与程序设计语言中数据类型概念的区别。 解:抽象数据类型包含一般数据类型的概念,但含义比一般数据类型更广、更抽象。一般数据类型由具体语言系统内部定义,直接提供给编程者定义用户数据,因此称它们为预定义数据类型。抽象数据类型通常由编程者定义,包括定义它所使用的数据和在这些数据上所进行的操作。在定义抽象数据类型中的数据部分和操作部分时,要求只定义到数据的逻辑结构和操作说明,不考虑数据的存储结构和操作的具体实现,这样抽象层次更高,更能为其他用户提供良好的使用接口。 1.3 设有数据结构(D,R),其中 {}4,3,2,1d d d d D =,{}r R =,()()(){}4,3,3,2,2,1d d d d d d r = 试按图论中图的画法惯例画出其逻辑结构图。 解: 1.4 试仿照三元组的抽象数据类型分别写出抽象数据类型复数和有理数的定义(有理数是其分子、分母均为自然数且分母不为零的分数)。 解: ADT Complex{ 数据对象:D={r,i|r,i 为实数} 数据关系:R={} 基本操作: InitComplex(&C,re,im) 操作结果:构造一个复数C ,其实部和虚部分别为re 和im DestroyCmoplex(&C) 操作结果:销毁复数C Get(C,k,&e) 操作结果:用e 返回复数C 的第k 元的值 Put(&C,k,e) 操作结果:改变复数C 的第k 元的值为e IsAscending(C) 操作结果:如果复数C 的两个元素按升序排列,则返回1,否则返回0

数据结构(C语言版)实验报告

数据结构(C语言版) 实验报告 学院计算机科学与技术 专业***** 学号**** 班级**** 姓名 *** 指导教师 ****

实验1 实验题目:单链表的插入和删除 实验目的: 了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。 实验要求: 建立一个数据域定义为字符串的单链表,在链表中不允许有重复的字符串;根据输入的字符串,先找到相应的结点,后删除之。 实验主要步骤: 1、分析、理解给出的示例程序。 2、调试程序,并设计输入数据(如:bat,cat,eat,fat,hat,jat,lat,mat,#),测 试程序的如下功能:不允许重复字符串的插入;根据输入的字符串,找到相应的结点并删除。 3、修改程序: (1)增加插入结点的功能。 (2)将建立链表的方法改为头插入法。 程序代码: #include"" #include"" #include"" #include"" typedef struct node . . 示意图:

head head head 心得体会: 本次实验使我们对链表的实质了解更加明确了,对链表的一些基本操作也更加熟练了。另外实验指导书上给出的代码是有一些问题的,这使我们认识到实验过程中不能想当然的直接编译执行,应当在阅读并完全理解代码的基础上再执行,这才是实验的意义所在。

实验2 实验题目:二叉树操作设计和实现 实验目的: 掌握二叉树的定义、性质及存储方式,各种遍历算法。 实验要求: 采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序和后序以及按层次遍历 的操作,求所有叶子及结点总数的操作。 实验主要步骤: 1、分析、理解程序。 2、调试程序,设计一棵二叉树,输入完全二叉树的先序序列,用#代表虚结点(空指针), 如ABD###CE##F##,建立二叉树,求出先序、中序和后序以及按层次遍历序列,求 所有叶子及结点总数。 实验代码 #include"" #include"" #include"" #define Max 20 ertex=a; irstedge=NULL; irstedge; G->adjlist[i].firstedge=s; irstedge; R[i] 留在原位

相关文档
最新文档