ImageVerifierCode 换一换
格式:DOCX , 页数:33 ,大小:76.66KB ,
资源ID:25643831      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/25643831.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(数据结构习题及答案与实验指导线性表2.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

数据结构习题及答案与实验指导线性表2.docx

1、数据结构习题及答案与实验指导线性表2第2章 线性表线性表是一种最基本、最常用的数据结构,它有两种存储结构顺序表和链表。本章主要介绍线性表的定义、表示和基本运算的实现。重点讨论了线性表的存储结构,以及在顺序、链式两种存储结构上基本运算的实现。重点提示: 线性表的逻辑结构特征 线性表的顺序存储和链式存储两种存储结构的特点 在两种存储结构下基本操作的实现2-1 重点难点指导2-1-1 相关术语1线性表线性表是具有相同数据类型的n(n0)个数据元素的有限序列,通常记为:(a1,a2,an),其中n为表长,n=0时称为空表。要点:一种逻辑结构,其数据元素属于相同数据类型,之间的关系是线性关系。2顺序表顺

2、序存储的线性表。要点:按线性表中的元素的逻辑顺序依次存放在地址连续的存储单元里,其存储特点:用物理上的相邻实现逻辑上的相邻。3链表用链表存储的线性表。要点:链表是通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,对每个结点的地址是否连续没有要求。4单链表每个结点除了数据域外还有一个指向其后继的指针域。要点:通常将每个元素的值和其直接后继的地址作为一个结点,通过每个结点中指向后继结点的指针表示线性表的逻辑结构。5头指针要点:头指针是一个指针变量,里面存放的是链表中首结点的地址,并以此来标识一个链表。如链表H,链表L等,表示链表中第一个结点的地址存放在指针变量H、L中。通常用头指针来惟

3、一标识一个链表。6头结点要点:附加在第一个元素结点之前的一个结点,头指针指向头结点。当该链表表示一个非空的线性表时,头结点的指针域指向第一个元素结点;为空表时,该指针域为空。7头结点的作用要点:其作用有两个,一是使对空表和非空表的处理得到统一;二是在链表的第一个位置上的操作和在其他位置上的操作一致,无需特殊处理。2-1-2 线性表的顺序存储1顺序表顺序存储的线性表称为顺序表。其特点是:用一组地址连续的存储单元来依次存放线性表的数据元素,因此数据元素的逻辑顺序和物理次序一致(这是顺序存储的核心所在)。具体实现:在程序设计语言中,一维数组在内存中占用的存储空间就是一组连续的存储区域,因此,用一维数

4、组来表示顺序表的数据存储区域是再合适不过的。考虑到线性表的运算有插入、删除等,即表长是可变的,因此,数组的容量需设计得足够大,设用dataMaxSize来表示,其中MaxSize是一个根据实际问题定义的足够大的整数,线性表中的数据从 data0 开始依次顺序存放,但当前线性表中的实际元素个数可能未达到MaxSize个,因此需用一个变量 last 记录当前线性表中最后一个元素在数组中的位置,即 last 起一个指针的作用,始终指向线性表中最后一个元素,因此,表空时last=-1。这种存储思想的具体实现可以是多样的。方法一:可以用一个数组和表示长度的变量共同完成上述思想,如:#define Max

5、Size /MaxSize为根据实际问题定义的足够大的整数DataType dataMaxSize; int last;这样表示的顺序表如图2-1所示。数据元素分别存放在data0到datalast中。这样使用简单方便,但有时不便管理。图2-1 线性表的顺序存储示意图方法二:从结构上考虑,通常将 data 和 last 封装成一个结构作为顺序表的类型:#define MaxSize /MaxSize为根据实际问题定义的足够大的整数typedef struct DataType dataMaxSize; int last; /表示线性表最后一个元素位置。 SeqList; 定义一个顺序表变量:S

6、eqList L ;这样表示的线性表如图2-2(a)所示。表长为L.last+1,线性表中的数据元素a1an分别存储在L.data0L.dataL.last中。方法三:由于教科书中的算法用Visual C+语言描述,根据Visual C+语言中的一些规则,有时定义一个指向SeqList 类型的指针更为方便:SeqList *L ;L是一个指针变量,线性表的存储空间通过 L=new SeqList操作(Visual C+语句,不同的语言版本可能有所不同)来获得。L中存放的是顺序表的地址,这样表示的线性表如图2-2(b)所示。表长表示为(*L).last+1或L-last+1,线性表中数据元素的存

7、储空间为:L-data0 L-dataL-last。读者通过上述介绍的几种表示方式,进一步体会顺序存储的“理念”,做题时根据题意灵活掌握,在读写算法时注意相关数据结构的类型说明。(b)表长为L-last+1(a)表长为L.last+166L.last 5L-last 5L-length 6a6a5a4a3a2a1a6a5a4a3a2a1032415MaxSize-1MaxSize-1345210L-dataL.data图2-2 线性表的顺序存储示意图2顺序表的优缺点优点1:顺序表是由地址连续的向量实现的,因此具有按序号随机访问的特点。设a的存储地址为Loc(a),每个数据元素占d个存储地址,则

8、第i个数据元素的地址为:Loc(ai)=Loc(a)+(i-1)*d 1in这就是说只要知道顺序表首地址和每个数据元素所占地址单元的个数就可求出第i个数据元素的地址来,这就是顺序表具有按数据元素的序号随机存取的特点。优点2:存储密度高。缺点1:在顺序表中做插入和删除运算时,平均需移动大约表中一半的元素;缺点2:顺序表的存储空间是静态分配的,在程序执行之前必须明确规定它的存储规模,因此分配不足则会造成溢出;分配过大,又可能造成存储单元的浪费。2-1-3 链表1单链表图2-3 单链表结点结构链表是通过一组任意的存储单元来存储线性表中的数据元素的,为建立起数据元素之间的线性关系,对每个数据元素ai,

9、除了存放数据元素自身的信息 ai 之外,还需要和ai一起存放其后继 ai+1 所在的存储单元的地址,这两部分信息组成一个“结点”,结点的结构如图2-3所示,每个元素都如此。因此n个元素的线性表通过每个结点的指针域拉成了一个“链子”,称之为链表。因为每个结点中只有一个指向后继的指针,所以称其为单链表。链表是由一个个结点构成的,结点定义如下:typedef struct Node DataType data; struct Node *next; LNode,*LinkList;LNode是结点的类型,*LinkList是指向LNode结点的指针类型。作为线性表的一种存储结构,我们关心的是结点间的

10、逻辑结构,而对每个结点的实际地址并不关心,所以通常的单链表用图2-4的形式表示。图2-4 单链表通常用“头指针”来标识一个单链表,如单链表L、单链表H等,是指某链表的第一个结点的地址放在了指针变量L、H中,头指针为“NULL”则表示一个空表。2单循环链表对于单链表而言,最后一个结点的指针域是空指针,如果将该链表的头指针置入该指针域,则使得链表头尾结点相连,就构成了单循环链表。对于单链表只能从头结点开始遍历整个链表,而对于单循环链表则可以从表中任意结点开始遍历整个链表,不仅如此,有时对链表常做的操作是在表尾、表头进行,此时可以改变一下链表的标识方法,不用头指针而用一个指向尾结点的指针R来标识,可

11、以使操作效率得以提高。3双向循环链表图2-5 双向链表在单链表的结点中只有一个指向其后继结点的指针域next,因此若已知某结点的指针为p,其后继结点的指针则为p-next,而找其前驱结点则只能从该链表的头指针开始,顺着各结点的next域进行,也就是说找后继结点的时间性能是O(1),找前驱的时间性能是O(n),如果希望找前驱结点的时间性能也达到O(1),则只能付出空间的代价:每个结点再加一个指向前驱结点的指针域,结点的结构如图2-5所示,用这种结点组成的链表称为双向链表。双向链表结点及指针类型定义如下:typedef struct DLNodeDataType data; struct DLNn

12、ode *prior,*next;DLNode,*DLinkList; 和单链表类似,双向链表通常也是用头指针标识。通过双向链表中某结点的指针p既可以直接得到它的后继结点的指针p-next,也可以直接得到它的前驱结点的指针p-prior。这样在有些操作中需要找前驱结点时,则勿需再用循环。设p指向双向循环链表中的某一结点,即p中是该结点的指针,则p-prior-next表示的是p所指结点之前驱结点的后继结点的指针,即与p相等;类似,p-next-prior表示的是p所指结点之后继结点的前驱结点的指针,也与p相等,所以有以下等式:p-prior-next = p = p-next-prior4静态

13、链表静态链表是指以数组方式存放链表的数据,数组的每个元素包含有数据域data和指针域next,这里的指针域next与链表中的指针域不同的是其存放的是该结点逻辑上的后继结点的相对地址(即在数组中的下标),也称之为静态指针。在以静态链表方式存储链表时,数组中含有两个单链表,一个是数据元素的链表,一个是空结点的链表,故还需要设置两个整型变量,分别用于存放链表首元素(或头结点)在数组中的位置和空结点链表的首位置。静态链表存储定义如下:#define MAXSIZE /足够大的数typedef struct DataType data; int next; SNode; /结点类型SNode sdMAX

14、SIZE; /数组sd以静态链表方式存放链表数据int SL,AV; /两个头指针变量5链式存储的优缺点链式存储的优缺点与顺序存储互补:优点1:对链表做插入和删除运算时,只需改变指针,不需移动数据。优点2:不需要事先分配空间,便于表的扩充。缺点1:存储密度降低,因为每个结点中除了存放数据元素的值还有一个指针域。缺点2:不具有按序号随机访问第i个元素的特点,必须通过标识链表的头指针(或尾指针)“顺藤摸瓜”才能找到第i个结点。2-1-4 线性表的基本运算1基于顺序表的运算顺序表中常做的运算有插入、删除、合并、查找等,做这些运算时,要掌握一个原则:时刻体现顺序存储的思想,即元素之间物理相邻和逻辑相邻

15、的一致性。(1)在顺序表中插入元素: 插入元素时,检查顺序表是否已满,已满则不能做插入操作。 根据具体问题确定插入位置。 移动有关元素,以便为待插入的元素让出位置来。 将元素插入。 修改表长。(2)在顺序表中删除元素: 检查顺序表是否已空,空则不能做删除运算。 根据具体问题确定删除元素的位置。 将其后面的有关元素移动,“挤掉”被删除的元素。 修改表长。结论:顺序表中插入一个数据元素平均需要移动(n+1)/2个元素。具体某一次的插入中,移动数据元素的个数与表长和插入位置有关。顺序表中删除一个数据元素需要平均移动n/2个元素。具体某一次的删除中,移动数据元素的个数与表长和删除元素的位置有关。2基于

16、链表的运算链表操作过程中,主要是指针的变化,因此必须清楚指针和动态结点的问题。(1)头结点的使用在对不带头结点的单链表进行操作时,对第一个结点的处理和其他结点是不同的。 头结点的加入完全是为了运算的方便,它的数据域无定义,指针域中存放的是第一个数据元素结点的地址,空表时为空。(2)插入 后插结点:设指针p指向单链表中某结点,s指向待插入的值为 x 的新结点,将s结点插入到p结点的后面,插入示意图如图2-6所示。操作如下:s-next=p-next;p-next=s;要点:两个指针的操作顺序不能交换。 前插结点设指针指向链表中某结点,s指向待插入的值为x的新结点,将s结点插入到p结点的前面,插入

17、示意图如图2-7所示,与后插不同的是:首先要找到p结点的前驱结点q,然后再完成在q结点之后插入s结点的操作,设单链表头指针为L,操作如下:q=L;while (q-next!=p) q=q-next; /找p的直接前驱s-next=q-next; q-next=s; 图2-6 在p之后插入s 图2-7 在p之前插入s后插操作的时间复杂性为O(1),前插操作因为要找 p 结点的前驱结点,时间性能为O(n);其实我们更关心的是数据元素之间的逻辑关系,所以仍然可以将 s 结点插入到 p 结点的后面,然后将p-data与s-data交换即可,这样既满足了逻辑关系,也能使得时间复杂性为O(1)。由此得知

18、:在单链表中插入一个结点必须知道其前驱结点。 在单链表第 i 个元素之前插入元素x. 从头指针开始找到第i-1个元素结点,若存在继续步骤,否则结束。. 申请、填装新结点。. 将新结点插入,结束。(3)删除 删除结点. 删除p结点的后继结点(假设存在),则可以直接完成:s=p-next;p-next=s-next;delete s;该操作的时间复杂性为O(1)。. 若要删除p结点,即p所指结点,通过示意图可见,要实现对结点p的删除,首先要找到p结点的前驱结点q,然后完成指针的操作即可。指针的操作由下列语句实现:q-next=p-next;delete p;显然找p结点前驱结点的时间复杂性为O(n

19、)。图2-8 删除p结点操作示意图如图2-8所示。当p结点有后继结点时,对p结点的删除可以这样处理:把结点p后继结点的值存储到结点p中,再删除结点p的后继结点,这样逻辑上删除了p结点,而时间性能为O(1)。 删除单链表的第i个结点在单链表中删除第i个结点,必须知道第i-1个结点的指针。算法思路:. 找到第i-1个结点;若存在继续步骤,否则结束。. 若存在第i个结点则继续步骤,否则结束。. 删除第i个结点,结束。(4)查找在单链表中按值查找或按序号查找某个元素,需通过头指针从第一个元素结点开始,逐个与x进行比较或记数,若查找成功,则返回指向该元素的指针,若查找失败,则返回NULL。(5)双向链表

20、中结点的插入图2-9 双向链表中的结点插入设p指向双向链表中某结点,s指向待插入的值为x的新结点,将*s所指结点插入到*p所指结点的前面,插入示意图如图2-9所示。操作如下: s-prior=p-prior; p-prior-next=s; s-next=p; p-prior=s;指针操作的顺序不是惟一的,但也不是任意的,操作必须要放到操作的前面完成,否则结点p的前驱结点的指针就丢掉了。读者把每条指针操作的涵义搞清楚,就不难理解了。图2-10 双向链表中结点的删除(6)双向链表中结点的删除设p指向双向链表中某结点,删除指针p所指结点。操作示意图如图2-10所示。操作如下: p-prior-ne

21、xt=p-next; p-next-prior=p-prior;delete p;2-2 典型例题解析2-2-1 选择题1带头结点的单链表head为空的判断条件是( )。Ahead=NULL Bhead-next=NULLChead-next=head Dhead!=NULL【分析】链表为空时,头结点的指针域为空。【答案】B2若某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用( )存储方式最节省运算时间。A单链表 B仅有头指针的单循环链表 C双链表 D仅有尾指针的单循环链表【分析】根据题意要求,该线性表的存储应能够很方便地找到线性表的第一个元素和最后一个元素,A和

22、B都能很方便地通过头指针找到线性表的第一个元素,却要经过所有元素才能找到最后一个元素;选项C双链表若存为双向循环链表,则能很方便地找到线性表的第一个元素和最后一个元素,但存储效率要低些,插入和删除操作也略微复杂;选项D可通过尾指针直接找到线性表的最后一个元素,通过线性表的最后一个元素的循环指针就能很方便地找到第一个元素。【答案】D3线性表的静态链表存储结构与顺序存储结构相比优点是( )。A所有的操作算法简单 B便于插入和删除C便于利用零散的存储器空间 D便于随机存取【分析】静态链表采用的是链式方式存储线性表,因此其具有链式存储的特点。【答案】B4若长度为n的线性表采用顺序存储结构,在其第i个位

23、置插入一个新元素算法的时间复杂度为( )。AO(log2n) BO(1)CO(n) DO(n2)【分析】在第i个位置上插入新元素需要从最后一个元素开始后移直到第i个元素后移为止,后移元素的次数为n-i+1,即时间复杂度为O(n)。【答案】C5将两个各有n个元素的有序表归并成一个有序表,其最少的比较次数是( )。An B2n-1 C2n Dn-1【分析】当一个表的最小元素大于另一个表的最大元素时比较次数为最少,共需n次。【答案】A6在双循环链表p所指结点之后插入s所指结点的操作是( )。Ap-next=s; s-prior=p; p-next-prior=s; s-prior=p-next;Bp

24、-next=s; p-next-prior=s; s-prior=p; s-next=p-next;Cs-prior=p; s-next=p-next; p-next=s; p-next-prior=s;Ds-prior=p; s-next=p-next; p-next-prior=s; p-next=s; 【分析】由于要将s所指结点插入到p所指结点之后,p结点为s结点的前驱,s结点为p结点的新后继,而结点p的原后继结点为结点s的后继结点,结点s为结点p的原后继结点的前驱结点。在选项A、B和C中均是先执行操作p-next=s,就是修改了结点p的后继结点为s结点,然后再执行操作p-next-pr

25、ior=s,因此,无法使得结点s为结点p的原后继结点的前驱结点,这样的赋值会使s结点为其自身的前驱。应先执行操作p-next-prior=s,再执行操作p-next=s。【答案】D7在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q结点和p结点之间插入s结点,则执行( )As-next=p-next;p-next=s;Bp-next=s-next;s-next=p;Cq-next=s; s-next=p;Dp-next=s; s-next=q;【分析】由于是将s所指结点插入到q和p所指结点之间,即使其为q所指结点的后继结点,为p所指结点的前驱结点,因此s-next的取值应为p,p-n

26、ext的取值无需改动,q-next的取值应改为s,故A、B和D均是错误的。【答案】C2-2-2 判断题1顺序存储的线性表可以按序号随机存取。【分析】因为顺序表在内存是用地址连续的空间存储的,设 a的存储地址为Loc(a),每个数据元素占d个存储地址,则第i个数据元素的地址为:Loc(ai)=Loc(a)+(i-1) *d 1=iprior = p-prior;p-prior=s;_s-next=p;【解答】只能是:s-prior-next=s; 而不能为:p-prior-next=s;因为在上面的第二条语句中已经改变了结点p的前驱结点,结点p的前驱结点已经为s结点,而不是操作前的前驱结点了。在

27、下面的语句顺序下,可有两个答案的选择。s-prior = p-prior;_p-prior=s;s-next=p;读者做这种题时,最好予以图示,不易出错。2已知线性表非递减有序,存储于一个一维数组A0.n-1 中(表长为n,设为全局量),下面算法的功能是什么?void del(DataType A ) int i,j; i=1; while(i=n-1)if (Ai!=Ai+1)i+; else for (j=(i+2);jnext) q=L;L=L-next;p=L; while (p-next)p=p-next; p-next=Q;q-next=NULL; return L; 【解答】算法的功能是把单链表的第一个结点从表头移到了链尾。返回的L指向原链表的第二个结点。若原链表表示的线性表是(a1, a2, an),则操作后表示的线性表为(a2, a3, an,a1)。4试描述头指针、头结点、开始结点的区别,并说明头指针和头结点的作用。【解答】头指针是一个指针变量,里面存放的是链表中首结点的地址,并以此来标识一个链表。如链表H,链表L等,表示链表中第一个结点的地址存放在H、L中。头结点是

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1