数据结构课件.ppt
- 文档编号:30779834
- 上传时间:2023-08-30
- 格式:PPT
- 页数:97
- 大小:608.50KB
数据结构课件.ppt
《数据结构课件.ppt》由会员分享,可在线阅读,更多相关《数据结构课件.ppt(97页珍藏版)》请在冰豆网上搜索。
第2章线性表,扬州大学信息学院王丽爱,2023/8/30,2,知识点,什么是线性表?
(逻辑结构)线性表如何存储?
(存储结构)不同存储方式下如何实现线性表的基本操作?
(操作),2023/8/30,3,第2章线性表,2.1线性表的类型定义2.2线性表的顺序表示和实现2.3线性表的链式表示和实现2.3.1线性链表2.3.2循环链表2.3.3双向链表2.3.4单链表应用举例,2023/8/30,4,2.1线性表的类型定义,定义线性表(Linear_List)是n个数据元素的有限序列。
说明数据元素根据需要可以不同(同一线性表中的数据元素具有相同属性,换句话说,属于某个数据对象)数据元素可以由若干个数据项(dataitem)组成,此时,常把数据元素称为记录(record),含有大量记录的线性表称为文件(file)举例字母表(A,B,C,D,Z)整数数据表(6,17,28,50,92,188)学生健康登记表,2023/8/30,5,2.1线性表的类型定义,学生健康登记表,2023/8/30,6,2.1线性表的类型定义,线性表中数据元素之间的关系可以排成一个线性序列:
(a1,a2,ai-1,ai,ai+1,an)其中n称作表的长度,当n=0时,称作空表。
非空表中,a1称为第1个元素,an称为最后一个元素,ai是第i个元素,称i为数据元素ai在线性表中的位序。
相邻两个数据元素之间存在着有序偶关系,ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。
2023/8/30,7,2.1线性表的类型定义,线性表的特点:
1.线性表中所有元素的性质相同。
即属于同一数据对象。
2.非空表中,除第一个和最后一个数据元素之外,其它数据元素有且仅有一个直接前驱元素和一个直接后继元素。
第一个数据元素a1无前驱,最后一个数据元素an无后继。
3.数据元素在表中的位置只取决于它自身的序号。
4.线性表的长度可以根据需要增长或缩短。
2023/8/30,8,2.1线性表的类型定义,ADTLinear_list,数据元素ai属于同一数据对象,i=1,2,3,n,n0结构对所有的数据元素存在次序关系操作设L为Linear_list类型的线性表,则可进行如下操作:
线性表初始化:
Init_List(L)初始条件:
表L不存在操作结果:
构造一个空的线性表求线性表的长度:
Length_List(L)初始条件:
表L存在操作结果:
返回线性表中的所含元素的个数取表元:
Get_List(L,i)初始条件:
表L存在且1=i=Length_List(L)操作结果:
返回线性表L中的第个元素的值或地址,2023/8/30,9,按值查找:
Locate_List(L,x),是给定的一个数据元素。
初始条件:
线性表L存在操作结果:
在表L中查找值为的数据元素,其结果返回在L中首次出现的值为的那个元素的序号或地址,称为查找成功;否则,在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。
2023/8/30,10,删除操作:
Delete_List(L,i)初始条件:
线性表L存在,1=i=n。
操作结果:
在线性表L中删除序号为i的数据元素,删除后使序号为i+1,i+2,.,n的元素变为序号为i,i+1,.,n-1,新表长原表长。
需要说明:
1.某数据结构上的基本运算,不是它的全部运算,而是一些常用的基本的运算。
2.每个操作在逻辑结构层次上尚不能用具体的某种程序语言写出具体的算法,算法的实现只有在存储结构确立之后。
2023/8/30,11,第2章线性表,2.1线性表的类型定义2.2线性表的顺序表示和实现2.3线性表的链式表示和实现2.3.1线性链表2.3.2循环链表2.3.3双向链表2.4一元多项式的表示及相加,2023/8/30,12,2.2线性表的顺序表示和实现,一、线性表的顺序表示用一组地址连续的存储单元依次存储线性表的数据元素假设每个元素需占l个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储地址设第i个数据元素的地址用LOC(ai)表示,则:
LOC(ai+1)=LOC(ai)+lLOC(ai)=LOC(a1)+(i-1)*l通常将LOC(a1)称为线性表的起始位置或基地址,2023/8/30,13,2.2线性表的顺序表示和实现,一、线性表的顺序表示线性表的这种机内表示称为线性表的顺序存储结构或顺序映像(sequentialmapping)通常,称这种存储结构的线性表为顺序表特点:
逻辑上相邻的元素物理上也相邻确定了线性表的基地址,线性表中任一元素的地址可以计算出来确定了线性表的基地址,表中任一元素都可随机存取线性表的顺序存储结构是一种随机存取的存储结构,2023/8/30,14,2.2线性表的顺序表示和实现,一、线性表的顺序表示,b,b+l,b+(i-1)l,b+(n-2)l,b+(n-1)l,b+nl,1,2,i,n-1,n,存储地址,数据元素在线性表中的位序,空闲,内存状态,2023/8/30,15,2.2线性表的顺序表示和实现,二、线性表顺序表示的实现顺序表的特点是可以随机存取高级程序设计语言中的数组类型也有随机存取的特性用数组来描述数据结构中的顺序存储结构,在Pascal中用一维数组来描述由于线性表的长度可变,且所需最大存储空间随问题不同而不同,如何处理?
2023/8/30,16,2.2线性表的顺序存储及运算实现,顺序表存储结构的表示可以是:
#defineMAXSIZE100TypedefstructElemType*data;intlast;SqList数据元素分别存放在data0到datalast中表长为last+1,表空时last=-1,2023/8/30,17,2.2线性表的顺序表示和实现,1.顺序表的初始化即构造一个空表将L设为指针参数,首先动态分配存储空间,然后,将表中last指针置为1,表示表中没有数据元素。
算法如下:
SeqList*init_SeqList()SeqList*L;L=malloc(sizeof(SeqList);L-last=-1;returnL;,2023/8/30,18,2.2线性表的顺序表示和实现,、顺序表的插入.1顺序表的插入,插入前,线性表长度增1,2023/8/30,19,2.2线性表的顺序表示和实现,.1顺序表的插入,x,2023/8/30,20,线性表的插入是指在表的第i个位置上插入一个值为x的新元素,插入后使原表长为n的表:
(a1,a2,.,ai-1,ai,ai+1,.,an)成为表长为n+1表:
(a1,a2,.,ai-1,x,ai,ai+1,.,an)。
i的取值范围为1=i=n+1。
顺序表上完成这一运算则通过以下步骤进行:
(1)将aian顺序向下移动,为新元素让出位置;
(2)将x置入空出的第i个位置;(3)修改last指针(相当于修改表长),使之仍指向最后一个元素。
2023/8/30,21,intInsert_SeqList(SeqList*L,inti,ElemTypex)intj;if(L-last=MAXSIZE1)printf(“表满”);return(-1);/*表空间已满,不能插入*/if(iL-last+2)/*检查插入位置的正确性*/printf(位置错);return(0);for(j=L-last;j=i-1;j-)L-dataj+1=L-dataj;/*结点移动*/L-datai-1=x;/*新元素插入*/L-last+;/*last仍指向最后元素*/return
(1);/*插入成功,返回*/,2023/8/30,22,2.2线性表的顺序表示和实现,2.2顺序表的插入算法的分析,顺序表上的插入运算,时间主要消耗在了数据的移动上,在第i个位置上插入x,从ai到an都要向后移动一个位置,共需要移动ni1个元素,而i的取值范围为:
1in+1,即有n1个位置可以插入。
设在第i个位置上作插入的概率为pi,则平均移动数据元素的次数:
2023/8/30,23,2.2线性表的顺序表示和实现,2.2顺序表的插入算法的分析,假设在线性表的任何位置上插入元素都是等概率的,则,2023/8/30,24,2.2线性表的顺序表示和实现,2.2顺序表的插入算法的分析,结论:
在顺序表中插入一个数据元素,平均移动约一半的元素若表长为n,则算法Ins_SqList的时间复杂度为O(n),2023/8/30,25,2.2线性表的顺序表示和实现,3.顺序表的删除.分析:
问题:
对线性表(a1,ai-1,ai,ai+1,an)删除数据元素ai思想:
将ai+1到an依次前移一个位置结果:
线性表(a1,ai-1,ai+1,an)注意:
必须按照从左到右的次序移动;删除结束后表长减一示例:
教材p24图2.4(略),2023/8/30,26,intDelete_SeqList(SeqList*L;inti)intj;if(iL-last+1)/*检查空表及删除位置的合法性*/printf(不存在第i个元素);return(0);for(j=i;jlast;j+)L-dataj-1=L-dataj;/*向上移动*/L-last-;return
(1);/*删除成功*/,2023/8/30,27,2.2线性表的顺序表示和实现,3.2顺序表的删除算法的分析,与插入运算相同,其时间主要消耗在了移动表中元素上,删除第i个元素时,其后面的元素ai+1an都要向前移动一个位置,共移动了n-i个元素设qi是删除第i个元素的概率,则在长度为n的线性表中删除一个元素时所需移动元素次数的期望值(平均次数)为:
2023/8/30,28,2.2线性表的顺序表示和实现,假定在线性表的任何位置上删除元素都是等概率的,即,3.2顺序表的删除算法的分析,2023/8/30,29,2.2线性表的顺序表示和实现,这说明顺序表上作删除运算时大约需要移动表中一半的元素显然算法Del_SqList的时间复杂度为O(n)。
3.2顺序表的删除算法的分析,2023/8/30,30,4.按值查找线性表中的按值查找是指在线性表中查找与给定值x相等的数据元素。
在顺序表中完成该运算最简单的方法:
从第一个元素a1起依次和x比较,直到找到一个与x相等的数据元素,则返回它在顺序表中的存储下标或序号(二者差一);或者查遍整个表都没有找到与x相等的元素,返回-1。
2.2线性表的顺序表示和实现,2023/8/30,31,算法如下:
intLocation_SeqList(SeqList*L,ElemTypex)inti=0;while(ilast/*返回的是存储位置*/,2.2线性表的顺序表示和实现,2023/8/30,32,本算法的主要运算是比较。
显然比较的次数与x在表中的位置有关,也与表长有关。
当a1=x时,比较一次成功。
当an=x时比较n次成功。
平均比较次数为(n+1)/2,时间性能为O(n)。
2.2线性表的顺序表示和实现,2023/8/30,33,2.2.1顺序表应用举例,例21将顺序表(a1,a2,.,an)重新排列为以a1为界的两部分:
a1前面的值均比a1小,a1后面的值都比a1大(这里假设数据元素的类型具有可比性,不妨设为整型)。
这一操作称为划分。
a1也称为基准。
2023/8/30,34,划分的方法有多种,下面介绍的划分算法其思路简单,性能较差。
基本思路:
从第二个元素开始到最后一个元素,逐一向后扫描:
(1)当前数据元素aI比a1大时,表明它已经在a1的后面,不必改变它与a1之间的位置,继续比较下一个。
(2)当前结点若比a1小,说明它应该在a1的前面,此时将它上面的元素都依次向下移动一个位置,然后将它置入最上方。
2.2.1顺序表应用举例,2023/8/30,35,voidpart(SeqList*L)inti,j;ElemTypex,y;x=L-data0;/*将基准置入x中*/for(i=1;ilast;i+)if(L-dataidatai;for(j=i-1;j=0;j-)/*移动*/Ldataj+1=L-dataj;L-data0=y;,2023/8/30,36,本算法中,有两重循环,外循环执行n1次,内循环中移动元素的次数与当前数据的大小有关,当第个元素小于a1时,要移动它上面的i-1个元素,再加上当前结点的保存及置入,所以移动i-1+2次,在最坏情况下,a1后面的结点都小于a1,故总的移动次数为:
即最坏情况下移动数据时间性能为()。
2023/8/30,37,例22有顺序表A和B,其元素均按从小到大的升序排列,编写一个算法将它们合并成一个顺序表C,要求C的元素也是从小到大的升序排列。
2.2.1顺序表应用举例,2023/8/30,38,算法思路:
依次扫描通过A和B的元素,比较当前的元素的值,将较小值的元素赋给C,如此直到一个线性表扫描完毕,然后将未完的那个顺序表中余下部分赋给C即可。
C的容量要能够容纳A、B两个线性表相加的长度。
2.2.1顺序表应用举例,2023/8/30,39,voidmerge(SeqListA,SeqListB,SeqList*C)inti,j,k;i=0;j=0;k=0;while(idatak+=A.datai+;elseC-datak+=B.dataj+;while(idatak+=A.datai+;while(jdatak+=B.dataj+;C-last=k-1;,算法的时间性能是O(m+n),其中m是A的表长,n是B的表长。
2023/8/30,40,2.2.1顺序表应用举例,例.编写一函数从一给定的顺序表A中删除元素值在x到y(x=y)之间的所有元素。
2023/8/30,41,算法思路:
先扫描,将xy之间的元素置成一个特殊的值(如0),并不立即删除它们。
然后从后往前扫描,遇到0再移动其后面的元素将其删除。
算法如下:
2023/8/30,42,voiddel(SeqList*A,ElemTypex,ElemTypey)for(i=0;ilast;i+)/先扫描if(A-datai=x,2023/8/30,43,voiddel(SeqList*A,ElemTypex,ElemTypey)for(i=A-last;i=0;i-)/从后往前扫描if(A-datai=x,2023/8/30,44,voiddel(SeqList*A,ElemTypex,ElemTypey)i=0;j=0;while(ilast)/从前往后扫描if(A-datai=x,2023/8/30,45,小结,顺序表的存贮特点:
用物理上的相邻实现了逻辑上的相邻;它要求用连续的存储单元顺序存储线性表中各元素,因此,对顺序表插入、删除时需要通过移动数据元素来实现,影响了运行效率。
2023/8/30,46,第2章线性表,2.1线性表的类型定义2.2线性表的顺序表示和实现2.3线性表的链式表示和实现2.3.1线性链表2.3.2循环链表2.3.3双向链表2.4一元多项式的表示及相加,2023/8/30,47,2.3线性表的链式表示和实现,顺序表:
逻辑上相邻的数据元素在物理上也相邻可以随机存取表中任一元素,每个元素的地址可用一个简单、直观的公式来表示插入或删除元素时,需要移动大量元素线性表的链式存储结构不要求逻辑上相邻的数据元素在物理上也相邻插入、删除时无需移动元素不能随机存取,2023/8/30,48,2.3.1线性链表,线性表的链式存储结构的特点:
用一组任意的存储单元(可以是连续的,也可以是不连续的)存放线性表的数据元素为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系对数据元素ai来说,除了存储其本身的信息外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)这两部分信息组成数据元素ai的存储映像,称为结点(node)结点包含两个域:
存储数据元素信息的数据域,存储直接后继存储位置的指针域指针域中存储的信息称为指针或链,2023/8/30,49,2.3.1线性链表,n个结点(ai的存储映像,1in)链结成一个链表,即为线性表(a1,a2,an)的链式存储结构。
此链表的每个结点中只包含一个指针域,故又称为线性链表或单链表,2023/8/30,50,2.3.1线性链表,示例:
(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG),NIL,头指针:
指示链表中第一个结点的存储位置,最后一个数据元素无直接后继,线性链表中最后一个结点的指针为空,2023/8/30,51,2.3.1线性链表,示例:
(ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG),2023/8/30,52,2.3.1线性链表,常用“头指针”来标识一个单链表,如单链表L、单链表H等,是指某链表的第一个结点的地址放在了指针变量L、H中,头指针为“NULL”则表示一个空表。
2023/8/30,53,2.3.1线性链表,带头结点的非空单链表带头结点的空链表,.,2023/8/30,54,2.3.1线性链表,描述:
线性表的链式存储结构可用C语言中的“指针”描述,线性表的单链表的存储结构;TypedefstructLNodeElemTypedata;structLNode*next;LNode,*LinkList;,2023/8/30,55,将操作中用到指向某结点的指针变量说明为LNode*类型,如LNode*p;则语句:
p=malloc(sizeof(LNode);则完成了申请一块LNode类型的存储单元的操作,并将其地址赋值给变量p。
P所指的结点为*p,*p的类型为LNode型,该结点的数据域为(*p).data或p-data,指针域为(*p).next或p-next。
free(p)则表示释放p所指的结点。
2023/8/30,56,单链表上基本运算的实现,1.建立单链表链表是一种动态管理的存储结构(顺序表不同)。
链表的每个结点占用的存储空间不是预先分配,而是运行时系统根据需求而生成的;建立单链表从空表开始,每读入一个数据元素则申请一个结点,插入到链表中。
(1)头部插入结点
(2)尾部插入结点,2.3.1线性链表,2023/8/30,57,头部插入结点LinkListCreat_LinkList1()LinkListL=NULL;/*空表*/Lnode*s;intx;/*设数据元素的类型为int*/scanf(%d,2023/8/30,58,
(2)尾部插入结点头插入建立单链表简单,但读入的数据元素的顺序与生成的链表中元素的顺序是相反的;用尾插入的方法,则可次序一致。
因为每次是将新结点插入到链表的尾部,所以需加入一个指针r用来始终指向链表中的尾结点,以便能够将新结点插入到链表的尾部。
2023/8/30,59,算法思路:
初始状态:
头指针H=NULL,尾指针r=NULL;按线性表中元素的顺序依次读入数据元素,不是结束标志时,申请结点,将新结点插入到r所指结点的后面,然后r指向新结点(但第一个结点有所不同,注意算法中的有关部分)。
2023/8/30,60,LinkListCreat_LinkList2()LinkListL=NULL;Lnode*s,*r=NULL;intx;/*设数据元素的类型为int*/scanf(%d,2023/8/30,61,说明:
第一个结点的处理和其它结点是不同的;第一个结点加入时链表为空,它没有直接前驱结点,它的地址就是整个链表的指针,需要放在链表的头指针变量中;其它结点有直接前驱结点,其地址放入直接前驱结点的指针域。
2023/8/30,62,注:
“第一个结点”问题的解决:
在链表的头部加入一个“头结点”;头结点的类型与数据结点一致,标识链表的头指针变量L中存放该结点的地址,它的数据域无定义,指针域中存放的是第一个数据结点的地址,空表时为空;即使是空表,头指针变量L也不为空(即对“空表”和“非空表”的处理一致);头结点的加入完全是为了运算的方便。
2023/8/30,63,LinkListCreat_LinkList1()LinkListL=NULL;/*空表*/Lnode*s;intx;/*设数据元素的类型为int*/scanf(%d,s-next=L-next;L-next=s;,L-next=NULL;,2023/8/30,64,LinkListCreat_LinkList2()LinkListL=NULL;Lnode*s,*r=NULL;intx;/*设数据元素的类型为int*/scanf(%d,L-next=NULL;,r-next=s;r=s;,2023/8/30,65,2.求表长算法思路:
设一个移动指针和计数器,初始化后,所指结点后面若还有结点,向后移动,计数器加1。
2023/8/30,66,
(1)设L是带头结点的单链表(线性表的长度不包括头结点)。
intLength_LinkList1(LinkListL)Lnode*p=L;/*p指向头结点*/intj=0;while(p-next)p=p-next;j+;/*p所指的是第j个结点*/returnj;自己算算时间复杂度,2023/8/30,67,
(2)设L是不带头结点的单链表。
intLength_LinkList2(LinkListL)Lnode*p=L;intj;if(p=NULL)return0;/*空表的情况*/j=1;/*在非空表的情况下,p所指的是第一个结点*/;while(p-next)p=p-next;j+;returnj;时间复杂度为?
2023/8/30,68,3.查找操作
(1)按序号查找Get_Linklist(L,i)算法思路:
从链表的第一个元素结点起,判断当前结点是否是第i个,若是,则返回该结点的指针,否则继续后一个,表结束为止。
没有第个结点时返回空。
2023/8/30,69,算法如下:
Lnode*Get_LinkList(LinkListL,Inti);/*在单链表L中查找第i个元素结点,找到返回其指针,否则返回空*/Lnode*p=L;intj=0;while(p-next!
=NULL时间复杂度?
2023/8/30,70,
(2)按值查找即定位Locate_LinkList(L,x)算法思路:
从链表的第一个元素结点起,判断当前结点其值是否等于x,若是,返回该结点的指针,否则继续后一个,表结束为止。
找不到时返回空。
2023/8/30,71,4.插入
(1)后插结点:
设p指向单链表中某结点,s指向待插入的值为x的新结点,将*s插入到*p的后面,插入示意图如左图。
操作如下:
s-next=p-next;p-next=s;注意:
两个指针的操作顺序不能交换。
2023/8/30,72,q=L;while(q-next!
=p)q=q-next;/*找*p的直接前驱*/s-next=q-next;q-next=s;,
(2)前插结点:
设指向链表中某结点,指向待插入的值为x的新结点,将*s插入到*p的前面.与后插不同的是:
首先要找到*p的前驱*q,然后再完成在*q之后插入*s,设单链表头指针为L.,2023/8/30,73,(3)插入运算Insert_LinkList(L,i,x)算法思路:
1.找到第i-1个结点;若存在继续2,否则结束2.申请、填装新
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课件