⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt

上传人:rrsccc 文档编号:10304642 上传时间:2021-05-07 格式:PPT 页数:46 大小:610KB
返回 下载 相关 举报
⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt_第1页
第1页 / 共46页
⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt_第2页
第2页 / 共46页
⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt_第3页
第3页 / 共46页
⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt_第4页
第4页 / 共46页
⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt_第5页
第5页 / 共46页
点击查看更多>>
资源描述

《⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt》由会员分享,可在线阅读,更多相关《⒈教学内容:2.1 线性表逻辑结构;2.2 线性表的顺序存储及运算实现.ppt(46页珍藏版)》请在三一文库上搜索。

1、2021年5月7日,数据结构讲义,1,教学内容:2.1 线性表逻辑结构; 2.2 线性表的顺序存储及运算实现; 2.3 线性表的链式存储和实现。 教学目的:理解线性表的定义及其运算; 理解顺序表和链表的定义、组织形式、结构特征和类型说明; 掌握在这两种表上实现的插入、删除和按值查找的算法; 了解循环链表、双(循环)链表的结构特点和在其上施加的插入、删除等操作。 教学重点:线性表的定义及逻辑上的特点; 顺序表上插入、删除和定位运算的实现; 单链表的结构特点及类型说明; 头指针和头结点的作用及区别; 定位、删除、插入运算在单链表上的实现; 循环链表、双链表的结构特点,循环链表、双链表上删除与插入运

2、算的实现。 教学难点:线性表与线性结构的联系与区别; 头结点在链表中的作用;指针操作; 删除、插入运算中的指针操作顺序; 双链表上指针的操作顺序。 教学时数: 8学时(含习题课2学时),第二章 线性表,2021年5月7日,数据结构讲义,2,2.1 线性表的逻辑结构,线性表的定义 线性表的基本操作,2021年5月7日,数据结构讲义,3,2.1.1 线性表的定义,线性表是一种线性结构。线性结构的特点是数据元素之间是一种线性关系,数据元素“一个接一个的排列”。在一个线性表中数据元素的类型是相同的,或者说线性表是由同一类型的数据元素构成的线性结构。 线性表是具有相同数据类型的n(n=0)个数据元素的有

3、限序列,通常记为: (a1,a2, ai-1,ai,ai+1,an) 其中n为表长, n0 时称为空表。 表中相邻元素之间存在着顺序关系。将 ai-1 称为 ai 的直接前趋,ai+1 称为 ai 的直接后继。就是说:对于ai,当 i=2,.,n 时,有且仅有一个直接前趋 ai-1.,当i=1,2,.,n-1 时,有且仅有一个直接后继 ai+1,而 a1 是表中第一个元素,它没有前趋,an 是最后一个元素无后继。 需要说明的是:ai为序号为 i 的数据元素(i=1,2,n),通常我们将它的数据类型抽象为datatype,datatype根据具体问题而定,如在学生情况信息表中,它是用户自定义的学

4、生类型; 在字符串中,它是字符型; 等等。,2021年5月7日,数据结构讲义,4,2.1.2 线性表的基本操作,线性表初始化:Init_List(L) 初始条件:表L不存在 操作结果:构造一个空的线性表 求线性表的长度:Length_List(L) 初始条件:表L存在 操作结果:返回线性表中的所含元素的个数 取表元:Get_List(L,i) 初始条件:表L存在且1=i=Length_List(L) 操作结果:返回线性表L中的第个元素的值或地址 按值查找:Locate_List(L,x),是给定的一个数据元素。 初始条件:线性表L存在 操作结果:返回在L中首次出现的值为的那个元素的序号或地址,

5、称为查找成功; 否则,在L中未找到值为的数据元素,返回一特殊值表示查找失败。 插入操作:Insert_List(L,i,x) 初始条件:线性表L存在,插入位置正确 (1=i=n+1,为插入前的表长)。 操作结果:在线性表L的第 i 个位置上插入一个值为 x 的新元素,这样使原序号为 i , i+1, . , n 的数据元素的序号变为 i+1,i+2, . , n+1,插入后表长=原表长+1。 删除操作:Delete_List(L,i) 初始条件:线性表L存在,1=i=n。 操作结果:在线性表L中删除序号为i的数据元素,删除后使序号为 i+1, i+2,., n 的元素变为序号为 i, i+1,

6、.,n-1,新表长原表长。,需要说明的是: 某数据结构上的基本运算,不是它的全部运算,而是一些常用的基本的运算,而每一个基本运算在实现时也可能根据不同的存储结构派生出一系列相关的运算来。 在上面各操作中定义的线性表仅仅是一个抽象在逻辑结构层次的线性表,尚未涉及到它的存储结构。,2021年5月7日,数据结构讲义,5,2.2 线性表的顺序存储及运算实现,线性表的顺序存储 顺序表上基本运算的实现 顺序表应用举例,2021年5月7日,数据结构讲义,6,2.2.1 线性表的顺序顺序存储,线性表的顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表的各元素,用这种存储形式存储的线性表称其为顺序表。

7、设 a的存储地址为Loc(a),每个数据元素占d个存储地址,则第i个数据元素的地址为: Loc(ai)=Loc(a)+(i-1)*d 1In 从结构性上考虑,通常将 data 和 last 封装成一个结构作为顺序表的类型: typedef struct datatype dataMAXSIZE; int last; SeqList;,2021年5月7日,数据结构讲义,7,2.2.2 顺序表上基本运算的实现 顺序表的初始化,顺序表的初始化即构造一个空表,对表是一个加工型的运算,因此,将 L设为指针参数,首先动态分配存储空间,然后,将表中 last 指针置为1,表示表中没有数据元素。,2021年5

8、月7日,数据结构讲义,8,插入运算,线性表的插入是指在表的第i个位置上插入一个值为 x 的新元素:,2021年5月7日,数据结构讲义,9,插入算法的时间性能分析,顺序表上的插入运算,时间主要消耗在了数据的移动上,在第i个位置上插入 x ,从 ai 到 an 都要向下移动一个位置,共需要移动 ni1个元素,而 i 的取值范围为 :1 i n+1,即有 n1个位置可以插入。设在第i个位置上作插入的概率为Pi,则平均移动数据元素的次数: 设:Pi=1/ (n+1) ,即为等概率情况,则: 这说明:在顺序表上做插入操作需移动表中一半的数据元素。显然时间复杂度为(n)。,2021年5月7日,数据结构讲义

9、,10,删除运算,线性表的删除运算是指将表中第 i 个元素从线性表中去掉。,2021年5月7日,数据结构讲义,11,删除算法的时间性能分析,与插入运算相同,其时间主要消耗在了移动表中元素上,删除第i个元素时,其后面的元素 ai+1an 都要向上移动一个位置,共移动了 n-i 个元素,所以平均移动数据元素的次数: 在等概率情况下,pi =1/ n,则: 这说明顺序表上作删除运算时大约需要移动表中一半的元素,显然该算法的时间复杂度为(n)。,2021年5月7日,数据结构讲义,12,按值查找,线性表中的按值查找是指在线性表中查找与给定值x相等的数据元素。,本算法的主要运算是比较。显然比较的次数与x在

10、表中的位置有关,也与表长有关。平均比较次数为(n+1)/2,时间性能为O(n)。,2021年5月7日,数据结构讲义,13,2.2.3 顺序表应用举例,例2.1 将顺序表 (a1,a2,. ,an) 重新排列为以 a1 为界的两部分:a1 前面的值均比 a1 小,a1 后面的值都比 a1 大。 划分的方法有多种,下面介绍的划分算法其思路简单,性能较差。 基本思路: 从第二个元素开始到最后一个元素,逐一向后扫描: 当前数据元素 aI 比 a1 大时,表明它已经在 a1 的后面,不必改变它与 a1 之间的位置,继续比较下一个。 当前结点若比 a1 小,说明它应该在 a1 的前面,此时将它上面的元素都

11、依次向下移动一个位置,然后将它置入最上方。,2021年5月7日,数据结构讲义,14,总的移动次数为 : 即最坏情况下移动数据时间性能为()。,2021年5月7日,数据结构讲义,15,例2.2 有顺序表A和B,其元素均按从小到大的升序排列,编写一个算法将它们合并成一个顺序表C,要求C的元素也是从小到大的升序排列。 算法思路:依次扫描通过A和B的元素,比较当前的元素的值,将较小值的元素赋给C,如此直到一个线性表扫描完毕,然后将未完的那个顺序表中余下部分赋给C即可。C的容量要能够容纳A、B两个线性表相加的长度。,2021年5月7日,数据结构讲义,16,算法的时间性能是O(m+n),其中m是A的表长,

12、n是B的表长。,2021年5月7日,数据结构讲义,17,例2.3 比较两个线性表的大小。两个线性表的比较依据下列方法:设A、B是两个线性表,均用向量表示,表长分别为m和n。 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=(x,z),B=(y,x,x,z),若A= B= 空表,则A=B;若A=空表且B空表,或两者均不空且A首元素小于B首元素,则AB。 算法思路:首先找出A、B的最大共同前缀;然后求出A和B,之后在按比较规则进行比较,AB 函数返回1;A=B返回0

13、;AB返回-1。,2021年5月7日,数据结构讲义,18,算法的时间性能是O( m+n )。,2021年5月7日,数据结构讲义,19,2.3 线性表的链式存储和运算实现,单链表 循环链表 双向链表 静态链表 单链表应用举例,2021年5月7日,数据结构讲义,20,2.3.1 单链表,链表是通过一组任意的存储单元来存储线性表中的数据元素的,对每个数据元素ai,除了存放数据元素的自身的信息 ai 之外,还需要和ai一起存放其后继 ai+1 所在的存贮单元的地址,这两部分信息组成一个“结点”。存放数据元素信息的称为数据域,存放其后继地址的称为指针域。 链表是由一个个结点构成的, 结点定义如下: ty

14、pedef struct node datatype data; struct node *next; LNode,*LinkList; 定义头指针变量: LinkList H;,2021年5月7日,数据结构讲义,21,2.3.2 单链表上基本运算的实现 建立单链表,在链表的头部插入结点建立单链表,2021年5月7日,数据结构讲义,22,在单链表的尾部插入结点建立单链表,2021年5月7日,数据结构讲义,23,求表长,设L是带头结点的单链表(线性表的长度不包括头结点)。,2021年5月7日,数据结构讲义,24,设L是不带头结点的单链表。,2021年5月7日,数据结构讲义,25,查找操作,按序号

15、查找 Get_Linklist(L,i) 算法思路:从链表的第一个元素结点起,判断当前结点是否是第i个,若是,则返回该结点的指针,否则继续后一个,表结束为止。没有第个结点时返回空指针。,2021年5月7日,数据结构讲义,26,按值查找即定位 Locate_LinkList(L,x) 算法思路:从链表的第一个元素结点起,判断当前结点值是否等于x,若是,返回该结点的指针,否则继续后一个,表结束为止。找不到时返回空指针。,算法2-12、算法2-13的时间复杂度均为O(n)。,2021年5月7日,数据结构讲义,27,插入操作,后插结点:设p指向单链表中某结点,s指向待插入的值为x的新结点,将*s插入到

16、*p的后面。 操作如下: s-next=p-next; p-next=s; 注意:两个指针的操作顺序不能交换。,2021年5月7日,数据结构讲义,28,前插结点:设指向链表中某结点,指向待插入的值为x的新结点,将*s插入到*p的前面。与后插不同的是:首先要找到*p的前驱*q,然后再完成在*q之后插入*s,设单链表头指针为L,操作如下: q=L; while (q-next!=p) q=q-next; /*找*p的直接前驱*/ s-next=q-next; q-next=s;,2021年5月7日,数据结构讲义,29,插入运算 Insert_LinkList(L,i,x) 算法思路:1.找到第i-

17、1个结点;若存在继续2,否则结束。 2.申请、填装新结点。 3.将新结点插入,结束。,算法2-14的时间复杂度为O(n)。,2021年5月7日,数据结构讲义,30,删除操作,设p指向单链表中某结点,删除*p。要实现对结点*p的 删除,首先要找到*p的前驱结点*q,然后完成指针的操作即可。指针的操作由下列语句实现: q-next=p-next; free(p); 显然找*p前驱的时间复杂性为O(n)。 若要删除*p的后继结点(假设存 在),则可以直接完成: s=p-next; p-next=s-next; free(s); 该操作的时间复杂性为O(1) 。,2021年5月7日,数据结构讲义,31

18、,删除运算:Del_LinkList(L,i) 算法思路:1.找到第i-1个结点;若存在继续2,否则结束。 2.若存在第i个结点则继续3,否则结束。 3.删除第i个结点,结束。,算法2-15的时间复杂度为O(n)。,2021年5月7日,数据结构讲义,32,2.3.3 循环链表,对于单链表而言,最后一个结点的指针域是空指针,如果将该链表头指针置入该指针域,则使得链表头尾结点相连,就构成了单循环链表。,在单循环链表上的操作基本上与非循环链表相同,只是将原来判断指针是否为NULL变为是否是头指针而已,没有其它较大的变化。 对于单循环链表则可以从表中任意结点开始遍历整个链表;另外,有时对链表常做的操作

19、是在表尾、表头进行,此时可以改变一下链表的标识方法,不用头指针而用一个指向尾结点的指针R来标识,可以使得操作效率提高。,2021年5月7日,数据结构讲义,33,例:对两个单循环链表H1 、H2的连接操作,是将H2的第一个数据结点接到H1的尾结点,如用头指针标识,则需要找到第一个链表的尾结点,其时间复杂性为O(n),而链表若用尾指针R、R2来标识,则时间性能为O(1)。操作如下: P= Rnext; /*保存第一个表的头结点指针*/ R-next=R2-next-next; /*头尾连接*/ free(R2-next); /*释放第二个表的头结点*/ R2-next=P; /*组成循环链表*/,

20、2021年5月7日,数据结构讲义,34,2.3.4 双向链表,单链表的结点中只有一个指向其后继结点的指针域next,找后继的时间性能是O(1),找前驱的时间性能是O(n);可以付出空间的代价使得找前驱的时间性达到O(1):每个结点再加一个指向前驱的指针域。用这种结点组成的链表称为双向链表。 双向链表结点的定义如下: typedef struct dlnode datatype data; struct dlnode *prior,*next; DLNode,*DLinkList;,2021年5月7日,数据结构讲义,35,和单链表类似,双向链表通常也是用头指针标识,也可以带头结点和做成循环结构。

21、通过某结点的指针p即可以直接得到它的后继结点的指针p-next,也可以直接得到它的前驱结点的的指针p-prior。这样在有些操作中需要找前驱时,则勿需再用循环。 p-prior-next = p= p-next-prior,2021年5月7日,数据结构讲义,36,在双向链表中插入一个结点: 设p指向双向链表中某结点,s指向待插入的值为x的新结点,将*s插入到*p的前面。操作如下: s-prior=p-prior; p-prior-next=s; s-next=p; p-prior=s; 上面指针操作的顺 序不是唯一的,但也 不是任意的,操作必须要放到操作的前面完成,否 则*p的前驱结点的指针就

22、丢掉了。,2021年5月7日,数据结构讲义,37,在双向链表中删除指定结点: 设p指向双向链表中某结点,删除*p。 操作如下: p-prior-next=p-next; p-next-prior=p-prior; free(p);,2021年5月7日,数据结构讲义,38,2.3.5 静态链表,首先看一个例子:规模较大的结构数组 sdMAXSIZE 中有两个链表:其中链表SL是一个带头结点的单链表,表示了线性表(a1, a2, a3, a4, a5),而另一个单链表AV是将当前 sd 中的空结点组成的链表。 数组sd的定义如下: #define MAXSIZE /*足够大的数*/ typedef

23、 struct datatype data; int next; SNode; /*结点类型*/ SNode sdMAXSIZE; int SL,AV; /*两个头指针变量*/,2021年5月7日,数据结构讲义,39,在例子中,SL是用户的线性表,AV模拟的是系统存储池中空闲结点组成的链表,当用户需要结点时,例如向线性表中插入一个元素,需自己向AV申请,而不能用系统函数malloc来申请,相关的语句为: if(AV != -1) t=AV; AV=sdAV.next; ; 所得到的结点地址(下标)存入了 t 中;不难看出当AV表非空时,摘下了第一个结点给用户。当用户不再需要某个结点时,需通过该

24、结点的相对地址 t 将它还给AV,相关语句为: sdt.next=AV; AV=t; 交给AV表的结点链在了AV的头部。,2021年5月7日,数据结构讲义,40,例 在带头结点的静态链表SL的第i个结点之前插入一个值为x的新结点。设静态链表的存储区域sd为全局变量。,2021年5月7日,数据结构讲义,41,2.3.6 单链表应用举例,例1 已知单链表H,写一算法将其倒置。,算法思路:依次取原链表中的每个结点,将其作为第一个结点插入到新链表中去,指针p用来指向原表中当前结点,p为空时结束。,2021年5月7日,数据结构讲义,42,例2 已知单链表L,写一算法,删除其重复结点。,算法思路:用指针p

25、指向第一个数据元素结点,从它的后继结点开始到表的结束,查找与其值相同的结点并删除之;p指向下一个结点;依此类推,p指向最后结点时算法结束。,2021年5月7日,数据结构讲义,43,例3 设有两个单链表A、B,其中元素递增有序,编写算法将A、B归并成一个按元素值递减(允许有相同值)有序的链表C,要求用A、B中的原结点形成,不能重新申请结点。 算法思路:利用A、B两表有序的特点,依次进行比较,将当前值较小者摘下,插入到C表的头部,得到的C表则为递减有序的。,2021年5月7日,数据结构讲义,44,2.4 顺序表和链表的比较,本章介绍了线性表的逻辑结构及它的两种存储结构:顺序表和链表。顺序存储有三个

26、优点: (1) 方法简单,各种高级语言中都有数组,容易实现。 (2) 不用为表示结点间的逻辑关系而增加额外的存储开销。 (3) 顺序表具有按元素序号随机访问的特点。,2021年5月7日,数据结构讲义,45,但它也有两个缺点: 在顺序表中做插入删除操作时,平均移动大约表中一半的元素,因此对n较大的顺序表效率低。 需要预先分配足够大的存储空间,估计过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。 链表的优缺点恰好与顺序表相反。,2021年5月7日,数据结构讲义,46,在实际中怎样选取存储结构呢?通常有以下几点考虑: 基于存储的考虑 对线性表的长度或存储规模难以估计时,不宜采用顺序表;链表不用事先估计存储规模,但链表的存储密度较低。 基于运算的考虑 如果经常做的运算是按序号访问数据元素,顺序表优于链表; 在顺序表中做插入、删除操作时平均移动表中一半的元素,在链表中作插入、删除操作,虽然也要找插入位置,但操作主要是比较操作,从这个角度考虑后者优于前者。 基于环境的考虑 顺序表容易实现,任何高级语言中都有数组类型,链表的操作是基于指针的,相对来讲前者简单些,也是用户考虑的一个因素。 总之,两种存储结构各有长短,选择那一种由实际问题中的主要因素决定。通常“较稳定”的线性表选择顺序存储,而频繁做插入删除的即动态性较强的线性表宜选择链式存储。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1